将`sys.stdout`重定向到文件或缓冲区

时间:2015-08-17 19:29:56

标签: python python-3.x stdout

我在Python 3.4中工作,我有一些我不理解的行为:如果我将stdout重定向到一个文件,我能够从子进程中捕获文本。但是,当我重定向到Python文件对象时,我停止捕获该输出。我很想解释(跟随)行为。

我有:

from multiprocessing import Process

def worker():
    print('forked output')

def output():
    print('redirected')
    p = Process(target=worker)
    p.daemon = True
    p.start()
    p.join()  # wait for subprocess to terminate
    print('end')

Python 3.4中的redirect_stdout上下文管理器使得stdout变得容易(在这个例子中)。

from contextlib import redirect_stdout
from sys import stdout
from tempfile import TemporaryFile


with TemporaryFile(mode='w+', encoding=stdout.encoding) as buf:
    with redirect_stdout(buf):
        output()  # the function defined above
    buf.seek(0)
    s = buf.read()
    print('output from TemporaryFile:')
    print(s)

然后我可以简单地调用脚本来获得以下输出:

$ python stackoverflow.py 
output from TemporaryFile:
redirected
forked output
end

这正是我想要的,并且工作正常。

我的困惑源于如果我将TemporaryFileTextIOWrapper切换,我脚本的行为会发生变化。

from io import BytesIO, TextIOWrapper


with TextIOWrapper(BytesIO(), stdout.encoding) as buf:
    with redirect_stdout(buf):
        output()  # the function defined at the start
    buf.seek(0)
    s = buf.read()
    print('output from TextIO:')
    print(s)

现在,当我调用程序时,我丢失了分叉进程的输出。

$ python stackoverflow.py 
output from TextIO:
redirected
end

发生了什么事?

我怀疑问题与TextIOWrapper对象没有文件描述符这一事实有关,而os.fork()(由multiprocessing使用)可能因此取代了TextIOWrapper与另一个人TextIOWrapper,但我承认在那里存在一些混淆(特别是考虑到stdout似乎是fileno() >>> from sys import stdout >>> stdout.fileno() 1 >>> stdout <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'> 已实施。)

<a>

感谢您提供任何信息。

1 个答案:

答案 0 :(得分:1)

由于您正在使用多处理,因此应使用该库提供的standard message passing primitives。不要从子进程中调用print();这是糟糕的设计。

如果您实际上尝试使用其他人的(非Python)代码,请使用subprocess.check_output()或其他子进程函数。