python stdout重定向_如何将python子进程stderr和stdout重定向到多个...

您可以创建自己的类似文件的类,将其写入多个文件句柄.这是一个简单的示例,其中包含重定向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

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

请注意,当数据可用于计划的协程时,数据将被写入文件.确切的时间取决于当前的系统负载.所以我将sleep 0.01命令放在multitest.bsh中,以保持对stdout和stderr行的处理同步.没有这种延迟,通常不会很好地交错q2中的stdout和stderr行.也许有更好的方法可以实现同步,但是我仍然是异步编程的新手.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值