Popen([...], stderr=PIPE) 忽略来自生成的 python 程序的 input() 消息

Popen([...], stderr=PIPE) ignores input() message from spawned python program

我有一个文件 运行通过 Popen() 连接另一个文件。

# a.py
import subprocess

p = subprocess.Popen(['python3','/home/scotty/b.py'], 
stderr=subprocess.PIPE)
p.wait()

# b.py
input('???')

当我运行a.py“???”没有出现,但提示仍然有效...为什么?我该如何解决?

如果我删除 stderr=subprocess.PIPE 那么“???”确实出现了。

根据文档,输入 "is written to standard output" 的输出,我没有触及标准输出。

似乎在你的例子中,一切都发生了,就好像为 stderr 打开管道而不是为 stdout 打开管道具有将 stdout 重定向到 stderr 的效果,因为在我所做的测试中,stderr 收到输入的提示。

下面是一个适用于我 linux 的代码。它可能过于复杂,因为我使用了 socketpairs,这当然不是必需的,但至少它是健壮的并且可以工作。

##################################
# a.py

import subprocess
import socket
import select

esock, echildsock = socket.socketpair()
osock, ochildsock = socket.socketpair()
p = subprocess.Popen(['python3','b.py'], 
    stderr=echildsock.fileno(),
    stdout=ochildsock.fileno())

while p.poll() is None:
    r, w, x = select.select([esock, osock],[],[], 1.0)
    if not r:
        continue # timed out
    for s in r:
        print('stdout ready' if s is osock else 'stderr ready')
        data = s.recv(1024)
        print('received', data.decode('utf8'))
osock.shutdown(socket.SHUT_RDWR)
osock.close()
esock.shutdown(socket.SHUT_RDWR)
esock.close()

##################################
# b.py

res = input('???')
print('in b:', res)