栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

显示子流程输出到stdout并将其重定向

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

显示子流程输出到stdout并将其重定向

要将子进程的stdout保存到变量中以进行进一步处理,并在子进程到达时将其显示出来,以显示该变量:

#!/usr/bin/env python3from io import StringIOfrom subprocess import Popen, PIPEwith Popen('/path/to/script', stdout=PIPE, bufsize=1,universal_newlines=True) as p, StringIO() as buf:    for line in p.stdout:        print(line, end='')        buf.write(line)    output = buf.getvalue()rc = p.returnpre

保存子进程的stdout和stderr都比较复杂,因为您应该同时使用两个流以避免死锁:

stdout_buf, stderr_buf = StringIO(), StringIO()rc =  teed_call('/path/to/script', stdout=stdout_buf, stderr=stderr_buf,     universal_newlines=True)output = stdout_buf.getvalue()...

在这里

teed_call()
定义。


更新: 这是一个更简单的

asyncio
版本。

要在单个线程中逐行同时捕获和显示子进程中的stdout和stderr,可以使用异步I / O:

#!/usr/bin/env python3import asyncioimport osimport sysfrom asyncio.subprocess import PIPE@asyncio.coroutinedef read_stream_and_display(stream, display):    """Read from stream line by line until EOF, display, and capture the lines.    """    output = []    while True:        line = yield from stream.readline()        if not line: break        output.append(line)        display(line) # assume it doesn't block    return b''.join(output)@asyncio.coroutinedef read_and_display(*cmd):    """Capture cmd's stdout, stderr while displaying them as they arrive    (line by line).    """    # start process    process = yield from asyncio.create_subprocess_exec(*cmd, stdout=PIPE, stderr=PIPE)    # read child's stdout/stderr concurrently (capture and display)    try:        stdout, stderr = yield from asyncio.gather( read_stream_and_display(process.stdout, sys.stdout.buffer.write), read_stream_and_display(process.stderr, sys.stderr.buffer.write))    except Exception:        process.kill()        raise    finally:        # wait for the process to exit        rc = yield from process.wait()    return rc, stdout, stderr# run the event loopif os.name == 'nt':    loop = asyncio.ProactorEventLoop() # for subprocess' pipes on Windows    asyncio.set_event_loop(loop)else:    loop = asyncio.get_event_loop()rc, *output = loop.run_until_complete(read_and_display(*cmd))loop.close()

旧版本:

这是一个基于以下

child_process.py
示例
tulip
的单线程解决方案:

import asyncioimport sysfrom asyncio.subprocess import PIPE@asyncio.coroutinedef read_and_display(*cmd):    """Read cmd's stdout, stderr while displaying them as they arrive."""    # start process    process = yield from asyncio.create_subprocess_exec(*cmd, stdout=PIPE, stderr=PIPE)    # read child's stdout/stderr concurrently    stdout, stderr = [], [] # stderr, stdout buffers    tasks = {        asyncio.Task(process.stdout.readline()): ( stdout, process.stdout, sys.stdout.buffer),        asyncio.Task(process.stderr.readline()): ( stderr, process.stderr, sys.stderr.buffer)}    while tasks:        done, pending = yield from asyncio.wait(tasks,     return_when=asyncio.FIRST_COMPLETED)        assert done        for future in done: buf, stream, display = tasks.pop(future) line = future.result() if line: # not EOF     buf.append(line)    # save for later     display.write(line) # display in terminal     # schedule to read the next line     tasks[asyncio.Task(stream.readline())] = buf, stream, display    # wait for the process to exit    rc = yield from process.wait()    return rc, b''.join(stdout), b''.join(stderr)

该脚本运行

'/path/to/script
命令并逐行同时读取其stdout&stderr。这些行将相应地打印到父级的stdout /
stderr,并另存为字节串以供将来处理。要运行
read_and_display()
协程,我们需要一个事件循环:

import osif os.name == 'nt':    loop = asyncio.ProactorEventLoop() # for subprocess' pipes on Windows    asyncio.set_event_loop(loop)else:    loop = asyncio.get_event_loop()try:    rc, *output = loop.run_until_complete(read_and_display("/path/to/script"))    if rc:        sys.exit("child failed with '{}' exit pre".format(rc))finally:    loop.close()


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/645307.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号