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

And*_*ham 7 python stdout python-3.x

我在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')
Run Code Online (Sandbox Code Playgroud)

redirect_stdoutPython 3.4中的上下文管理器使得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)
Run Code Online (Sandbox Code Playgroud)

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

$ python stackoverflow.py 
output from TemporaryFile:
redirected
forked output
end
Run Code Online (Sandbox Code Playgroud)

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

我的困惑来自,如果我,如果我切换事实茎TemporaryFile用TextIOWrapper,我的脚本的行为变化.

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)
Run Code Online (Sandbox Code Playgroud)

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

$ python stackoverflow.py 
output from TextIO:
redirected
end
Run Code Online (Sandbox Code Playgroud)

到底是怎么回事?

我怀疑这个问题与TextIOWrapper对象没有文件描述符这一事实有关,而且os.fork()(由...使用multiprocessing)因此可能会替换TextIOWrapper另一个,但我承认有些混乱(特别是考虑到stdout似乎是TextIOWrapper 已 fileno()实施).

>>> from sys import stdout
>>> stdout.fileno()
1
>>> stdout
<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
Run Code Online (Sandbox Code Playgroud)

感谢您提供任何信息.

Kev*_*vin 1

由于您使用的是多处理,因此您应该使用该库提供的标准消息传递原语。不要print()从子流程中调用;这是糟糕的设计。

如果您实际上尝试使用其他人的(非 Python)代码来实现此功能,请改用subprocess.check_output()或另一个子流程函数。