Question

I am trying to do a CVS login from Python by calling the cvs.exe process. When calling cvs.exe by hand, it prints a message to the console and then waits for the user to input the password.

When calling it with subprocess.Popen, I've noticed that the call blocks. The code is

subprocess.Popen(cvscmd, shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE,
    stderr = subprocess.PIPE)

I assume that it blocks because it's waiting for input, but my expectation was that calling Popen would return immediately and then I could call subprocess.communicate() to input the actual password. How can I achieve this behaviour and avoid blocking on Popen?

OS: Windows XP
Python: 2.6
cvs.exe: 1.11

Was it helpful?

Solution

  • Remove the shell=True part. Your shell has nothing to do with it. Using shell=True is a common cause of trouble.
  • Use a list of parameters for cmd.

Example:

cmd = ['cvs', 
       '-d:pserver:anonymous@bayonne.cvs.sourceforge.net:/cvsroot/bayonne', 
       'login']
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) 

This won't block on my system (my script continues executing). However since cvs reads the password directly from the terminal (not from standard input or output) you can't just write the password to the subprocess' stdin.

What you could do is pass the password as part of the CVSROOT specification instead, like this:

:pserver:<user>[:<passwd>]@<server>:/<path>

I.e. a function to login to a sourceforge project:

import subprocess

def login_to_sourceforge_cvs(project, username='anonymous', password=''):
    host = '%s.cvs.sourceforge.net' % project
    path = '/cvsroot/%s' % project
    cmd = ['cvs', 
           '-d:pserver:%s:%s@%s:%s' % (username, password, host, path), 
           'login']
    p = subprocess.Popen(cmd, stdin=subprocess.PIPE, 
                              stdout=subprocess.PIPE
                              stderr=subprocess.STDOUT) 
    return p

This works for me. Calling

login_to_sourceforge_cvs('bayonne')

Will log in anonymously to the bayonne project's cvs.

OTHER TIPS

If you are automating external programs that need input - like password - your best bet would probably be to use pexpect.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top