【问题标题】:Decorate CLI program with subprocess.Popen用 subprocess.Popen 装饰 CLI 程序
【发布时间】:2026-02-05 04:30:01
【问题描述】:

我想装饰python.exe。例如,当我们在交互模式下写入 stdin 和从 stdout 前缀读取时,它可能只是 Input:\nOutput:\n

python.exe

$ python
Python 3.6.1 |Anaconda custom (64-bit)| (default, Mar 22 2017, 20:11:04) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print(2)
2
>>> 2 + 2
4
>>>

除装饰python.exe:

$ decorated_python
Output:
Python 3.6.1 |Anaconda custom (64-bit)| (default, Mar 22 2017, 20:11:04) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 
Input:
print(2)
Output:
2
>>> 
Input:
2 + 2
Output:
4
>>>

我认为应该是这样的:

import subprocess

pid = subprocess.Popen("python".split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

while True:
    pid.stdin.write(input('Input:\n').encode())
    print('Output:\n' + pid.stdout.readlines())

pid.stdout.readlines() 从未完成。

我也尝试使用communicate 方法,但它只在第一次工作:

import subprocess

pid = subprocess.Popen("python".split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

while True:
    print('Output:\n', pid.communicate(input('Input:\n').encode()))

测试:

Input:
print(1)
Output:
 (b'1\r\n', b'')
Input:
pritn(1)
Traceback (most recent call last):
  File "C:/Users/adr-0/OneDrive/Projects/Python/AdrianD/temp/tmp.py", line 6, in <module>
    print('Output:\n', pid.communicate(input('Input:\n').encode()))
  File "C:\Users\adr-0\Anaconda3.6\lib\subprocess.py", line 811, in communicate
    raise ValueError("Cannot send input after starting communication")
ValueError: Cannot send input after starting communication

也许我只是错过了一些东西,因为如果我把2 放在python 中,我会得到2。但是我不能用communicate方法得到这个2

纯蟒蛇:

>>> 2
2

communicate方法装饰:

Input:
2
Output:
 (b'', b'')

【问题讨论】:

    标签: python subprocess command-line-interface stdout stdin


    【解决方案1】:

    如果您查看 python 文档,您会发现在使用 stdin/stdout=PIPE 时,几乎不建议不要对这些流使用读/写操作,因为这会导致死锁 - 您在执行 readlines 时实际经历过: https://docs.python.org/2/library/subprocess.html#popen-objects

    下一个问题到期了

    “Popen.communicate() 是一种辅助方法,它一次性将数据写入标准输入并创建线程以从标准输出和标准错误中提取数据。它在完成写入数据时关闭标准输入并读取标准输出和标准错误,直到那些管道关闭。您无法进行第二次通信,因为孩子在返回时已经退出。” @tdelaney

    更多信息: Multiple inputs and outputs in python subprocess communicate

    一般做交互式子进程比较难,你可以试试 https://pexpect.readthedocs.io/en/stable/

    【讨论】: