Python子进程将孩子的输出到文件和终端?
Posted
技术标签:
【中文标题】Python子进程将孩子的输出到文件和终端?【英文标题】:Python subprocess get children's output to file and terminal? 【发布时间】:2011-06-26 10:43:11 【问题描述】:我正在运行一个脚本,该脚本使用
执行许多可执行文件subprocess.call(cmdArgs,stdout=outf, stderr=errf)
当outf
/errf
为 None 或文件描述符时(stdout
/stderr
的不同文件)。
有什么方法可以执行每个 exe,以便将 stdout 和 stderr 一起写入文件和终端?
【问题讨论】:
asyncio version Python Popen: Write to stdout AND log file simultaneously的可能重复 【参考方案1】:call()
函数就是 Popen(*args, **kwargs).wait()
。您可以直接调用Popen
并使用stdout=PIPE
参数从p.stdout
中读取:
#!/usr/bin/env python
import sys
from subprocess import Popen, PIPE
from threading import Thread
def tee(infile, *files):
"""Print `infile` to `files` in a separate thread."""
def fanout(infile, *files):
with infile:
for line in iter(infile.readline, b""):
for f in files:
f.write(line)
t = Thread(target=fanout, args=(infile,) + files)
t.daemon = True
t.start()
return t
def teed_call(cmd_args, **kwargs):
stdout, stderr = [kwargs.pop(s, None) for s in ["stdout", "stderr"]]
p = Popen(
cmd_args,
stdout=PIPE if stdout is not None else None,
stderr=PIPE if stderr is not None else None,
**kwargs
)
threads = []
if stdout is not None:
threads.append(
tee(p.stdout, stdout, getattr(sys.stdout, "buffer", sys.stdout))
)
if stderr is not None:
threads.append(
tee(p.stderr, stderr, getattr(sys.stderr, "buffer", sys.stderr))
)
for t in threads:
t.join() # wait for IO completion
return p.wait()
outf, errf = open("out.txt", "wb"), open("err.txt", "wb")
assert not teed_call(["cat", __file__], stdout=None, stderr=errf)
assert not teed_call(["echo", "abc"], stdout=outf, stderr=errf, bufsize=0)
assert teed_call(["gcc", "a b"], close_fds=True, stdout=outf, stderr=errf)
【讨论】:
感谢您的快速响应,但它不起作用。外部进程只能看到操作系统级别的文件句柄(您从文件对象的 fileno() 方法获得的数字)。见bytes.com/topic/python/answers/541085-extend-file-type 谢谢,如果我想使用 subprocess.Popen(而不是 Call)运行多个 exec,而不是 subprocess.Call,你会怎么做,每个 exec 写入不同的文件和终端 @user515766:解决方法是一样的:将stdout
、stderr
设置为PIPE
,当你想写多个地方时调用tee()
。
有人删除了证明第一条评论(“不起作用”)错误的 cmets。它混淆了subprocess.call
和现在称为teed_call
的函数call
(不同)以避免歧义。
@Peilonrayz:我已使答案中的代码与 Python 2/3 兼容。 (它是 2011 年的纯 Python 2 解决方案)【参考方案2】:
你可以使用这样的东西: https://github.com/waszil/subpiper
在您的回调中,您可以做任何您喜欢的事情,记录、写入文件、打印等。它还支持非阻塞模式。
from subpiper import subpiper
def my_stdout_callback(line: str):
print(f'STDOUT: line')
def my_stderr_callback(line: str):
print(f'STDERR: line')
my_additional_path_list = [r'c:\important_location']
retcode = subpiper(cmd='echo magic',
stdout_callback=my_stdout_callback,
stderr_callback=my_stderr_callback,
add_path_list=my_additional_path_list)
【讨论】:
我用 cmd='python3 run2.py' 试过这个,但得到一个错误。我是否遗漏了如何将 run2.py 作为参数发送的内容:FileNotFoundError: [Errno 2] No such file or directory: 'python3 run2.py': 'python3 run2.py'以上是关于Python子进程将孩子的输出到文件和终端?的主要内容,如果未能解决你的问题,请参考以下文章
Jupyter notebook 中 Python 子进程的实时标准输出输出