简体   繁体   English

希望控制台输入而不会阻塞的Spawn子进程?

[英]Spawn subprocess that expects console input without blocking?

I am trying to do a CVS login from Python by calling the cvs.exe process. 我试图通过调用cvs.exe进程从Python登录CVS。 When calling cvs.exe by hand, it prints a message to the console and then waits for the user to input the password. 手动调用cvs.exe时,它将消息打印到控制台,然后等待用户输入密码。

When calling it with subprocess.Popen, I've noticed that the call blocks. 当使用subprocess.Popen调用它时,我注意到该调用阻塞了。 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. 我认为它阻塞是因为它正在等待输入,但是我的期望是调用Popen会立即返回,然后我可以调用subprocess.communicate()输入实际的密码。 How can I achieve this behaviour and avoid blocking on Popen? 如何实现此行为并避免在Popen上阻塞?

OS: Windows XP 操作系统:Windows XP
Python: 2.6 的Python:2.6
cvs.exe: 1.11 cvs.exe:1.11

  • Remove the shell=True part. 除去shell=True零件。 Your shell has nothing to do with it. 您的外壳与此无关。 Using shell=True is a common cause of trouble. 使用shell=True是造成麻烦的常见原因。
  • Use a list of parameters for cmd. 使用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. 但是,由于cvs直接从终端读取密码(而不是从标准输入或输出),因此您不能仅将密码写入子进程的stdin。

What you could do is pass the password as part of the CVSROOT specification instead, like this: 您可以做的是改为将密码作为CVSROOT规范的一部分传递,如下所示:

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

Ie a function to login to a sourceforge project: 即用于登录Sourceforge项目的函数:

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. 将匿名登录到bayonne项目的简历。

如果要自动执行需要输入的外部程序(例如密码),则最好的选择是使用pexpect

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM