这个问题已经在这里有了答案: Python subprocess get children’s output to file and terminal? 2个我只想将stderr和stdout重定向到多个文件.例如:s...

这个问题已经在这里有了答案: > Python subprocess get children’s output to file and terminal? 2个
我只想将stderr和stdout重定向到多个文件.
例如:
stderr应该重定向到file_1和file_2.
我在下面使用重定向输出到单个文件.
subprocess.Popen("my_commands",shell=True,stdout=log_file,stderr=err_file,executable="/bin/bash")
上面的东西将stdout和stderr重定向到单个文件.
有人可以告诉我这样做的方法吗(将输出重定向到文件log_file和err_file,例如stdout应该重定向到log_file和err_file,而stderr应该重定向到err_file和new_file)
解决方法:
您可以创建自己的类似文件的类,将其写入多个文件句柄.这是一个简单的示例,其中包含重定向sys.stdout和sys.stderr的测试.
import sys
class MultiOut(object):
def __init__(self, *args):
self.handles = args
def write(self, s):
for f in self.handles:
f.write(s)
with open('q1', 'w') as f1, open('q2', 'w') as f2, open('q3', 'w') as f3:
sys.stdout = MultiOut(f1, f2)
sys.stderr = MultiOut(f3, f2)
for i, c in enumerate('abcde'):
print(c, 'out')
print(i, 'err', file=sys.stderr)
运行该代码后,这些文件包含以下内容:
Q1
a out
b out
c out
d out
e out
Q3
0 err
1 err
2 err
3 err
4 err
Q2
a out
0 err
b out
1 err
c out
2 err
d out
3 err
e out
4 err
FWIW,如果您愿意,您甚至可以这样做:
sys.stdout = MultiOut(f1, f2, sys.stdout)
sys.stderr = MultiOut(f3, f2, sys.stderr)
不幸的是,像MultiOut这样的文件对象不能与Popen一起使用,因为Popen通过底层OS文件描述符访问文件,即,它希望OS认为它是文件,因此只有提供有效fileno方法的Python对象才可以.可以用于Popen的文件参数.
相反,我们可以使用Python 3的asyncio功能执行shell命令,并同时复制其stdout和stderr输出.
首先,这是一个简单的Bash脚本,我用来测试以下Python代码.就像前面的Python示例一样,它只是循环遍历数组,将数组内容回显到stdout,将数组索引回显到stderr.
multitest.bsh
#!/usr/bin/env bash
a=(a b c d e)
for((i=0; i<${#a[@]}; i++))
do
echo "OUT: ${a[i]}"
echo "ERR: $i" >&2
sleep 0.01
done
产量
OUT: a
ERR: 0
OUT: b
ERR: 1
OUT: c
ERR: 2
OUT: d
ERR: 3
OUT: e
ERR: 4
这是运行multitest.bsh的Python 3代码,将其stdout输出传输到文件q1和q2,并将stderr输出传输到q3和q2.
import asyncio
from asyncio.subprocess import PIPE
class MultiOut(object):
def __init__(self, *args):
self.handles = args
def write(self, s):
for f in self.handles:
f.write(s)
def close(self):
pass
@asyncio.coroutine
def copy_stream(stream, outfile):
""" Read from stream line by line until EOF, copying it to outfile. """
while True:
line = yield from stream.readline()
if not line:
break
outfile.write(line) # assume it doesn't block
@asyncio.coroutine
def run_and_pipe(cmd, fout, ferr):
# start process
process = yield from asyncio.create_subprocess_shell(cmd,
stdout=PIPE, stderr=PIPE, executable="/bin/bash")
# read child's stdout/stderr concurrently
try:
yield from asyncio.gather(
copy_stream(process.stdout, fout),
copy_stream(process.stderr, ferr))
except Exception:
process.kill()
raise
finally:
# wait for the process to exit
rc = yield from process.wait()
return rc
# run the event loop
loop = asyncio.get_event_loop()
with open('q1', 'wb') as f1, open('q2', 'wb') as f2, open('q3', 'wb') as f3:
fout = MultiOut(f1, f2)
ferr = MultiOut(f3, f2)
rc = loop.run_until_complete(run_and_pipe("./multitest.bsh", fout, ferr))
loop.close()
print('Return code:', rc)
运行代码后,这些文件包含以下内容:
Q1
OUT: a
OUT: b
OUT: c
OUT: d
OUT: e
Q3
ERR: 0
ERR: 1
ERR: 2
ERR: 3
ERR: 4
Q2
OUT: a
ERR: 0
OUT: b
ERR: 1
OUT: c
ERR: 2
OUT: d
ERR: 3
OUT: e
ERR: 4
异步代码从J.F. Sebastian’s answer变为问题Subprocess.Popen: cloning stdout and stderr both to terminal and variables.谢谢,J.F!
请注意,当数据可用于计划的协程时,数据将被写入文件.确切的时间取决于当前的系统负载.所以我将sleep 0.01命令放在multitest.bsh中,以保持对stdout和stderr行的处理同步.没有这种延迟,通常不会很好地交错q2中的stdout和stderr行.也许有更好的方法可以实现同步,但是我仍然是异步编程的新手.
本文标题为:如何将python子进程stderr和stdout重定向到多个文件?


基础教程推荐
- Python子进程调用不能使用grep 2023-11-13
- python lxml在dev_appserver(gae,windows)中不可用 2023-11-14
- Python子进程模块比命令慢得多(不建议使用) 2023-11-16
- windows下如何安装Python、pandas 2023-09-03
- Python re.findall中正则表达式(.*?)和参数re.S使用 2022-09-02
- python_django ubuntu下第一个程序helloworld 2023-11-13
- Numpy安装、升级与卸载的详细图文教程 2022-10-20
- Windows 下update pip 报错:Cannot remove entries from nonexistent file c:\intelpython3\lib\site-packa 2023-09-04
- python数据结构:数据类型 2023-08-05
- Python多线程入门学习 2023-08-04