我正在使用子进程模块启动子进程并连接到它的输出流(stdout).我希望能够在其标准输出上执行非阻塞读取.有没有办法让.readline非阻塞或在我调用之前检查流上是否有数据.readline?我希望这是可移植的,或至少在Windows和Linux下工作.
这是我现在如何做到的(.readline如果没有数据可用,则阻止它):
p = subprocess.Popen('myprogram.exe', stdout = subprocess.PIPE)
output_str = p.stdout.readline()
Run Code Online (Sandbox Code Playgroud) 要从我的Python脚本启动程序,我使用以下方法:
def execute(command):
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = process.communicate()[0]
exitCode = process.returncode
if (exitCode == 0):
return output
else:
raise ProcessException(command, exitCode, output)
Run Code Online (Sandbox Code Playgroud)
因此,当我启动一个类似的过程时Process.execute("mvn clean install"),我的程序会一直等到过程结束,然后我才能获得程序的完整输出.如果我正在运行需要一段时间才能完成的过程,这很烦人.
我可以让我的程序逐行写入进程输出,通过在循环结束之前轮询进程输出或其他内容吗?
**[编辑]抱歉,在发布此问题之前我没有很好地搜索.线程实际上是关键.在这里找到一个示例,说明如何执行此操作:** 来自线程的Python Subprocess.Popen
这是一个跟进这个问题,但如果我想传递一个参数stdin来subprocess,我怎么能得到实时输出?这就是我现在拥有的; 我也尝试从模块替换Popen,这只会导致脚本挂起.callsubprocess
from subprocess import Popen, PIPE, STDOUT
cmd = 'rsync --rsh=ssh -rv --files-from=- thisdir/ servername:folder/'
p = Popen(cmd.split(), stdout=PIPE, stdin=PIPE, stderr=STDOUT)
subfolders = '\n'.join(['subfolder1','subfolder2'])
output = p.communicate(input=subfolders)[0]
print output
Run Code Online (Sandbox Code Playgroud)
在前一个我没有通过的问题stdin我被建议使用p.stdout.readline,那里没有任何空间来管道stdin.
附录:这适用于转移,但我只看到输出的结尾,我希望看到转移的细节发生时.
我有一个进程,它是这样创建的:
p = subprocess.Popen(args = './myapp',
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
universal_newlines=True)
Run Code Online (Sandbox Code Playgroud)
后来,我试着写p的stdin:
p.stdin.write('my message\n')
Run Code Online (Sandbox Code Playgroud)
该myapp过程具有以下设置:
q = queue.Queue()
def get_input():
for line in iter(sys.stdin.readline, ''):
q.put(line)
sys.stdin.close()
threading.Thread(name = 'input-getter',
target = get_input).start()
Run Code Online (Sandbox Code Playgroud)
它正在尝试不断读取新行,如下所示:
try:
print('input:', q.get_nowait())
except Empty:
print('no input')
Run Code Online (Sandbox Code Playgroud)
不幸的是,子进程从不接收任何消息.当然,当我使用时:
p.communicate('my message\n')
Run Code Online (Sandbox Code Playgroud)
子进程临危消息,但正如所料,communicate方法关闭p的stdin,所以没有更多的沟通正在进行.
在此先感谢您的帮助.我是python的新手,甚至更新的HTML.
过去几天我一直在尝试创建一个带有按钮的网页,以便在家庭服务器上执行任务.
目前我有一个python脚本生成一个带按钮的页面:
(See the simplified example below. removed code to clean up post)
Run Code Online (Sandbox Code Playgroud)
然后是一个python脚本,它运行所述命令并输出到iframe页面上:
(See the simplified example below. removed code to clean up post)
Run Code Online (Sandbox Code Playgroud)
这会在命令完成后输出整个完成的输出.我也尝试将-u选项添加到python脚本以运行它无缓冲.我也尝试过使用Python subprocess.如果它有助于我运行的命令类型apt-get update,以及其他用于移动文件和修复文件夹权限的Python脚本.
当从普通的Ubuntu服务器终端运行时它运行正常并实时输出,并且从我的研究中它应该在命令运行时输出.
谁能告诉我哪里出错了?我应该使用其他语言来执行此功能吗?
编辑简化示例:
初始页面:
#runcmd.html
<head>
<title>Admin Tasks</title>
</head>
<center>
<iframe src="/scripts/python/test/createbutton.py" width="650" height="800" frameborder="0" ALLOWTRANSPARENCY="true"></iframe>
<iframe width="650" height="800" frameborder="0" ALLOWTRANSPARENCY="true" name="display"></iframe>
</center>
Run Code Online (Sandbox Code Playgroud)
创建按钮的脚本:
cmd_page = '<form action="/scripts/python/test/runcmd.py" method="post" target="display" >' + '<label for="run_update">run updates</label><br>' + '<input align="Left" type="submit" value="runupdate" name="update" title="run_update">' + "</form><br>" …Run Code Online (Sandbox Code Playgroud) python ×5
subprocess ×4
nonblocking ×2
cgi ×1
html ×1
io ×1
linux ×1
python-3.x ×1
stdin ×1
web ×1