我正在使用子进程模块启动子进程并连接到它的输出流(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) 我用subprocess模块调用不同的进程.但是,我有一个问题.
在以下代码中:
callProcess = subprocess.Popen(['ls', '-l'], shell=True)
Run Code Online (Sandbox Code Playgroud)
和
callProcess = subprocess.Popen(['ls', '-l']) # without shell
Run Code Online (Sandbox Code Playgroud)
两者都有效.阅读文档后,我开始知道这shell=True意味着通过shell执行代码.这意味着在缺席的情况下,该过程将直接启动.
那么我应该更喜欢我的情况 - 我需要运行一个进程并获得其输出.从shell内部或外部调用它有什么好处.
要从我的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
我正在使用Python subprocess.communicate()来从一个运行大约一分钟的进程中读取stdout.
如何stdout以流式方式打印出该流程的每一行,以便我可以看到生成的输出,但在继续之前仍然阻止流程终止?
subprocess.communicate() 似乎立刻提供所有输出.
我正在寻找从python调用shell脚本的方法,并使用日志记录将他们的stdout和stderr写入文件.这是我的代码:
import logging
import tempfile
import shlex
import os
def run_shell_command(command_line):
command_line_args = shlex.split(command_line)
logging.info('Subprocess: \"' + command_line + '\"')
process_succeeded = True
try:
process_output_filename = tempfile.mktemp(suffix = 'subprocess_tmp_file_')
process_output = open(process_output_filename, 'w')
command_line_process = subprocess.Popen(command_line_args,\
stdout = process_output,\
stderr = process_output)
command_line_process.wait()
process_output.close()
process_output = open(process_output_filename, 'r')
log_subprocess_output(process_output)
process_output.close()
os.remove(process_output_filename)
except:
exception = sys.exc_info()[1]
logging.info('Exception occured: ' + str(exception))
process_succeeded = False
if process_succeeded:
logging.info('Subprocess finished')
else:
logging.info('Subprocess failed')
return process_succeeded
Run Code Online (Sandbox Code Playgroud)
我确信无需创建临时文件来存储流程输出就可以实现.有任何想法吗?
我正在运行一个脚本,通过使用执行许多可执行文件
subprocess.call(cmdArgs,stdout=outf, stderr=errf)
Run Code Online (Sandbox Code Playgroud)
when outf/ errf是None或文件描述符(stdout/的不同文件stderr).
有什么方法可以执行每个exe,以便将stdout和stderr一起写入文件和终端?
我试图在Python中找到一种方法来运行其他程序:
这是我到目前为止所得到的...方法1:
def method1(command):
## subprocess.communicate() will give us the stdout and stderr sepurately,
## but we will have to wait until the end of command execution to print anything.
## This means if the child process hangs, we will never know....
proc=subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, executable='/bin/bash')
stdout, stderr = proc.communicate() # record both, but no way to print stdout/stderr in real-time
print ' ######### REAL-TIME ######### '
######## Not Possible
print ' ########## RESULTS ########## …Run Code Online (Sandbox Code Playgroud) 我正在使用这些选项(以及其他选项)围绕 Python Flask webapp 运行 uwsgi,以在标准输出上获取 JSON 编码的日志记录:
fmt=$'{"timestamp": "${strftime:%FT%TZ}", "level": "DEBUG", "name": "uwsgi", "message": "${msg}"}\n'
uwsgi --env="TZ=UTC" --log-encoder="json ${fmt}" --logformat="%(status) [%(msecs)ms] %(method) %(uri)"
Run Code Online (Sandbox Code Playgroud)
这很好地编码了来自 uwsgi 的标准输出,但不幸的是也编码了来自我的应用程序的日志记录,它已经是 JSON 格式,所以我得到如下内容:
{"timestamp": "2017-10-02T22:48:11Z", "level": "DEBUG", "name": "uwsgi", "message": "spawned uWSGI http 1 (pid: 75298)"}
{"timestamp": "2017-10-02T22:48:15Z", "level": "DEBUG", "name": "uwsgi", "message": "{\"timestamp\": \"2017-10-02T22:48:15.200Z\", \"message\": \"Descriptor requested\", \"request\": \"c6b08680-a7c3-11e7-9495-186590cba8eb\", \"name\": \"myapp.main\", \"level\": \"INFO\"}"}
{"timestamp": "2017-10-02T22:48:15Z", "level": "DEBUG", "name": "uwsgi", "message": "200 [11ms] GET /descriptor.json"}
Run Code Online (Sandbox Code Playgroud)
中间记录与 uwsgi 的其他输出使用相同的 JSON 编码。
如何避免 Flask 应用程序的输出被编码,但保持 uwsgi …
如何使用 subprocess.Popen 从命令获取输出,并为 stdout 和 stderr 提供单独的回调,但确保按照来自进程的行的顺序调用这些回调?
如果我不关心分离 STDOUT 和 STDERR 那么我可以这样做:
fd = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
line = fd.stdout.readline()
while line :
callback( line )
line = fd.stdout.readline()
Run Code Online (Sandbox Code Playgroud)
但是,如果我有stdoutCallback和stderrCallback,并且希望它们在适当的输出上调用,但按照与上述代码调用的顺序相同callback,我将如何去做呢?
已经有很多答案可以解决如何执行此常规操作,但是我的主要问题是为什么这种方法行不通?
我正在尝试从子进程“实时流式传输” stdout和stderr。我可以这样做:
import sys
import subprocess
def run_command(cmd):
process = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
for out in iter(process.stdout.readline, b''):
print(out)
for err in iter(process.stderr.readline, b''):
print(err)
run_command(['echo', 'hello', 'world']) # should print hello world
run_command(['rm', 'blarg223']) # Should print to stderr (file doesnt exist)
Run Code Online (Sandbox Code Playgroud)
这可以给我结果:
b'hello world\n'
b'rm: cannot remove \xe2\x80\x98blarg223\xe2\x80\x99: No such file or directory\n'
Run Code Online (Sandbox Code Playgroud)
但是,这会引起问题,因为它实际上仅实时输出标准输出,然后将所有错误打印到末尾。所以我想我可以使用以下方法解决此问题:
def run_command(cmd):
process = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
for out, err in zip(iter(process.stdout.readline, b''), iter(process.stderr.readline, b'')):
print(out)
print(b'Error: ' + err)
Run Code Online (Sandbox Code Playgroud)
但是,这不会产生任何输出。为什么使用zip无效?
python ×10
subprocess ×9
logging ×2
io ×1
nonblocking ×1
parent ×1
pexpect ×1
pty ×1
python-3.x ×1
tty ×1
uwsgi ×1