如何在使用管道后将子流程控制传递给常规stdin



我想做的是,在Python中,通过stdin以编程方式向进程发送一些初始命令,然后将输入传递给用户,让他们随后控制程序。Python程序应该简单地等待,直到子进程由于用户输入而退出。本质上,我想做的是:

import subprocess
p = subprocess.Popen(['cat'], stdin=subprocess.PIPE)
# Send initial commands.
p.stdin.write(b"threeninitialncommandsn")
p.stdin.flush()
# Give over control to the user.
# …Although stdin can't simply be reassigned
# in post like this, it seems.
p.stdin = sys.stdin
# Wait for the subprocess to finish.
p.wait()

我如何将stdin传递回用户(不使用raw_input,因为我需要用户的输入在每次按键后生效,而不仅仅是在按下回车键之后(?

不幸的是,在该进程的持续时间内,没有标准的方法可以将您自己的stdin拼接到其他进程的stdin,除非您首先选择写入该进程,然后从自己的stdin中读取并写入该进程。

也就是说,你可以这样做:

proc = subprocess.Popen(...)  # no stdin=

并且该进程将继承您的stdin;或者你可以这样做:

proc = subprocess.Popen(..., stdin=subprocess.PIPE, ...)

然后将stdin提供给该进程。但是,一旦您选择提供其任何的stdin,您就提供其所有,即使这意味着您必须读取自己的stdin。

Linux提供了一个splice系统调用(man7.org上的文档,Linux.die.net上的文档、维基百科、Linux将数据从文件描述符管道传输到fifo(,但最好的选择可能是使用后台线程来复制数据。

所以搜索同样的东西,至少在我的情况下,pexpect库会处理这个问题:

https://pexpect.readthedocs.io/en/stable/

p = pexpect.spawn("ssh myhost")
p.sendline("some_line")
p.interact()

正如它的名字一样,在将它移交给用户之前,您可以自动进行大量交互。

请注意,在您的情况下,您可能需要一个输出筛选器:在pexpect 中同时使用expect((和interact((

最新更新