繁体   English   中英

使用 asyncio 将 bash 作为 Python 的子进程运行,但 bash 提示被延迟

[英]Running bash as a subprocess to Python using asyncio, but bash prompts are delayed

我希望从 Python 的 asyncio 控制一个长时间运行的交互式 Bash 子进程,一次发送一个命令,然后从它接收结果。

The code fragment below works perfectly well in Python 3.7.0, Darwin Kernel Version 16.7.0, except that Bash prompts do not appear immediately on stderr , but appear to "queue up" until something else writes to stderr .

这是一个问题,因为原程序需要收到Bash提示才知道前面的命令已经执行完毕。

from asyncio.subprocess import PIPE
import asyncio


async def run():
    proc = await asyncio.create_subprocess_exec(
        '/bin/bash', '-i', stdin=PIPE, stdout=PIPE, stderr=PIPE
    )

    async def read(stream):
        message = 'E' if stream is proc.stderr else 'O'
        while True:
            line = await stream.readline()
            if line:
                print(message, line)
            else:
                break

    async def write():
        for command in (b'echo PS1=$PS1', b'ls sub.py', b'ls DOESNT-EXIST'):
            proc.stdin.write(command + b'\n')
            await proc.stdin.drain()
            await asyncio.sleep(0.01)  # TODO: need instead to wait for prompt

    await asyncio.gather(
        read(proc.stderr),
        read(proc.stdout),
        write(),
    )


asyncio.run(run())

结果:

E b'bash: no job control in this shell\n'
O b'PS1=\\u@\\h:\\w$\n'
O b'sub.py\n'
E b'tom@bantam:/code/test/python$ tom@bantam:/code/test/python$ tom@bantam:/code/test/python$ ls: DOESNT-EXIST: No such file or directory\n'

注意最后三个提示都是一起出来的,而且只有一次是故意造成的错误。 期望的行为当然是提示在它们发生时立即出现。

使用proc.stderr.read()而不是proc.stderr.read()会产生更多代码,但结果相同。

看到bash: no job control in this shell消息出现在stderr中,我有点惊讶,因为我正在运行bash -i ,但我想知道是否有这个问题,因为$PS1 PS19CCE69Z无法更进一步。

这让我呆了半天,但是当我写完问题后,我花了十分钟才想出一个解决方法。

如果我修改提示使其以\n结尾,那么proc.stderr实际上已被刷新,并且一切都运行得非常完美。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM