我正在使用Python subprocess.communicate()来从一个运行大约一分钟的进程中读取stdout.
如何stdout以流式方式打印出该流程的每一行,以便我可以看到生成的输出,但在继续之前仍然阻止流程终止?
subprocess.communicate() 似乎立刻提供所有输出.
我想将python脚本的子进程'stdout和stdin指向同一个文件.我不知道的是如何使两个来源的线条区分开来?(例如,带有感叹号的stderr行前缀.)
在我的特定情况下,不需要对子进程进行实时监视,执行的Python脚本可以等待其执行结束.
我有一个python子进程,我正在尝试从中读取输出和错误流.目前我有它的工作,但我只能在读完stderr之后阅读stdout.这是它的样子:
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout_iterator = iter(process.stdout.readline, b"")
stderr_iterator = iter(process.stderr.readline, b"")
for line in stdout_iterator:
# Do stuff with line
print line
for line in stderr_iterator:
# Do stuff with line
print line
Run Code Online (Sandbox Code Playgroud)
如您所见,stderrfor循环在stdout循环完成之前无法启动.如何修改它以便能够以正确的顺序读取这两行?
澄清:我仍然需要能够判断一条线是否来自stdout或者stderr因为我的代码中它们的处理方式不同.
我尝试完成的任务是流式传输ruby文件并打印出输出.(注意:我不想一次打印出所有内容)
main.py
from subprocess import Popen, PIPE, STDOUT
import pty
import os
file_path = '/Users/luciano/Desktop/ruby_sleep.rb'
command = ' '.join(["ruby", file_path])
master, slave = pty.openpty()
proc = Popen(command, bufsize=0, shell=True, stdout=slave, stderr=slave, close_fds=True)
stdout = os.fdopen(master, 'r', 0)
while proc.poll() is None:
data = stdout.readline()
if data != "":
print(data)
else:
break
print("This is never reached!")
Run Code Online (Sandbox Code Playgroud)
ruby_sleep.rb
puts "hello"
sleep 2
puts "goodbye!"
Run Code Online (Sandbox Code Playgroud)
问题
流文件工作正常.hello/goodbye输出以2秒延迟打印.正如脚本应该工作.问题是readline()最后会挂起而永不退出.我从未到过最后一个印刷品.
我知道有很多这样的问题,这里有一个stackoverflow但是没有它们让我解决问题.我不是那个整个子流程的东西,所以请给我一个更实际/具体的答案.
问候
编辑
修复意外的代码.(与实际错误无关)
是否可以修改以下代码以从'stdout'和'stderr'打印输出:
代码:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import subprocess
def run_cmd(command, cwd=None):
p = subprocess.Popen(command, cwd=cwd, shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
outs, errs = p.communicate()
rc = p.returncode
outs = outs.decode('utf-8')
errs = errs.decode('utf-8')
return (rc, (outs, errs))
Run Code Online (Sandbox Code Playgroud)
感谢@unutbu,特别感谢@ jf-sebastian,最终功能:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
from queue import Queue
from subprocess import PIPE, Popen
from threading import Thread
def read_output(pipe, funcs):
for line in iter(pipe.readline, b''):
for func in funcs: …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一起写入文件和终端?
我有一个需要 tty (如 stdin 和 stderr)的可执行文件,并且希望能够测试它。我想输入 stdin,并捕获 stdout 和 stderr 的输出,这是一个示例脚本:
# test.py
import sys
print("stdin: {}".format(sys.stdin.isatty()))
print("stdout: {}".format(sys.stdout.isatty()))
print("stderr: {}".format(sys.stderr.isatty()))
sys.stdout.flush()
line = sys.stdin.readline()
sys.stderr.write("read from stdin: {}".format(line))
sys.stderr.flush()
Run Code Online (Sandbox Code Playgroud)
我可以在没有 tty 的情况下运行它,但是它会被捕获.isatty并且每个都返回 False:
import subprocess
p = subprocess.Popen(["python", "test.py"], stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.write(b"abc\n")
print(p.communicate())
# (b'stdin: False\nstdout: False\nstderr: False\n', b'read from stdin: abc\n')
Run Code Online (Sandbox Code Playgroud)
我想捕获 stdout 和 stderr 并让所有三个返回 True - 作为 tty。
我可以用来pty制作 tty 标准输入:
import subprocess
m, s = pty.openpty()
p = subprocess.Popen(["python", "test.py"], …Run Code Online (Sandbox Code Playgroud) 如何使用 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调用的子进程的输出.为此我使用Popen(因为我不认为如果使用subprocess.call就可以管道stdout).
截至目前,我有两种方法可以做到这一点,在测试中,它似乎提供了相同的结果.代码如下:
with Popen(['Robocopy', source, destination, '/E', '/TEE', '/R:3', '/W:5', '/log+:log.txt'], stdout=PIPE) as Robocopy:
for line in Robocopy.stdout:
line = line.decode('ascii')
message_list = [item.strip(' \t\n').replace('\r', '') for item in line.split('\t') if item != '']
print(message_list[0], message_list[0])
Robocopy.wait()
returncode = Robocopy.returncode
Run Code Online (Sandbox Code Playgroud)
和
with Popen(['Robocopy', source, destination, '/E', '/TEE', '/R:3', '/W:5', '/log+:log.txt'], stdout=PIPE, universal_newlines=True, bufsize=1) as Robocopy:
for line in Robocopy.stdout:
message_list = [item.strip() for item in line.split('\t') if item != '']
print(message_list[0], message_list[2])
Robocopy.wait()
returncode = Robocopy.returncode
Run Code Online (Sandbox Code Playgroud)
第一种方法不包括universal_newlines = True,因为文档说明这只有在universal_newlines …
示例测试文件(print.py):
import sys
print('stdout')
print('stderr', file=sys.stderr)
Run Code Online (Sandbox Code Playgroud)
运行它的代码(x.py):
import subprocess
cmd = ['python', 'print.py']
print(subprocess.check_output(cmd, universal_newlines=True, stderr=subprocess.STDOUT))
Run Code Online (Sandbox Code Playgroud)
如果我从 shell 运行 print.py,它会首先打印 stdout。但是,如果我运行 x.py,它会首先打印 stderr。有什么办法可以让我以正确的顺序获得输出?