Python 由导入的模块生成的捕获子流程输出
注意:我知道我可以使用stdout=subprocess.PIPE捕获子流程输出 在我的例子中,子进程将由导入的模块启动,例如,youtube dl将为ffmpeg启动子进程,我希望捕获ffmpeg输出 我做了一个虚拟的工作场景来阐明我的观点 我有两个文件:m1.py我的模块和m2.py导入的库 m2.pyPython 由导入的模块生成的捕获子流程输出,python,subprocess,stdout,Python,Subprocess,Stdout,注意:我知道我可以使用stdout=subprocess.PIPE捕获子流程输出 在我的例子中,子进程将由导入的模块启动,例如,youtube dl将为ffmpeg启动子进程,我希望捕获ffmpeg输出 我做了一个虚拟的工作场景来阐明我的观点 我有两个文件:m1.py我的模块和m2.py导入的库 m2.py import subprocess def run(): print('m2 module message will be caught by echo function too')
import subprocess
def run():
print('m2 module message will be caught by echo function too')
cmd = ['ping', 'google.com']
subprocess.Popen(cmd)
m1.py
终端输出:
m1 module message will be caught by echo function
m2 module message will be caught by echo function too
Pinging google.com [172.217.18.46] with 32 bytes of data:
Reply from 172.217.18.46: bytes=32 time=86ms TTL=53
Reply from 172.217.18.46: bytes=32 time=78ms TTL=53
out.txt
m1 module message will be caught by echo function
m2 module message will be caught by echo function too
从上面可以清楚地看到out.txt文件从两个模块接收到2 print语句,但无法获得其他输出
这里的问题是,我如何获得m2.py启动的ping命令的输出,当然我不能更改m2.py的代码,因为它是第三方库,每周更新一次。注意:这可能只是部分响应,因为它的操作系统级别较低。它在linux上对我有效,但我不能就windows或其他操作系统发表声明 使用echo函数重定向输出的尝试不起作用,因为这只是覆盖python进程中的写操作。 ping命令或第三方模块启动的任何命令都是一个新进程,它不会继承python环境,特别是不会继承重写的write函数 但是-当生成一个新进程时,它确实继承了stdout文件句柄,我指的是低级别的os文件句柄,对于unix上的stdout,它是1 我可以用以下代码重定向ping输出
import os
...
out2 = open('out2.txt', 'w')
fd = out2.fileno() # here you get the low level file handle of the new file obj
os.dup2(fd, 1) # here you are closing your stdout handle and setting it to out2
...
m2.run() # the spawned ping command is now writing to out2
现在,这是重定向到文件对象。
我知道您想读取程序中的输出
要实现这一点,您可以在python中创建管道并改用该文件句柄:
pipein, pipeout = os.pipe()
注意,pipein和pipeout已经是低级文件句柄。要像使用python文件对象一样使用其中一个对象,您可以使用os.fdopenfd创建一个对象,只需返回子流程运行的结果并正常分配即可 平方米 m1
希望这有帮助它看起来很有希望,只是在windows上测试了相同的代码,并在out2.txt中收集了所有输出,正如您所说,我只需要回显输出以将其用于gui,因此我将检查os.pipe并让您知道结果。幸运的是,我无法更改导入模块m2.py中的任何代码,它是第三方库,但出于好奇,我尝试了你的代码,它抛出了一个错误TypeError:“Popen”对象不是很糟糕,我忘了添加通信。这就是导致输出错误的原因。我已对我的回答作了更正。如果您确定子流程对象是从m2模块返回的,那么这应该有效。不,子流程对象不是从m2模块返回的,无论如何,谢谢
pipein, pipeout = os.pipe()
import subprocess
def run():
print('m2 module message will be caught by echo function too')
cmd = ['ping', 'google.com']
return subprocess.Popen(cmd)
import sys
import m2
# this is a redirection function to echo stdout to a file
def echo(text):
with open('out.txt', 'a') as f:
f.write(text)
sys.stdout.write = original
sys.stdout.write(text)
sys.stdout.write = echo
original = sys.stdout.write
sys.stdout.write = echo
print('m1 module message will be caught by echo function')
process_object = m2.run()
output, err = process_object.communicate()
print(output, err)