【发布时间】:2020-03-18 17:06:20
【问题描述】:
示例
我注意到 cli 应用程序 ngrok 的这种行为。仅对本例来说是特殊的,因为它污染了父进程终端。它的核心功能并不重要。
获取可执行文件:
wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
unzip ngrok-stable-linux-amd64.zip
# There is `ngrok` executable in this dir now
产生问题的代码:
# ngrok_python.py
# It's in the same dir as the ngrok executable
import pty
import subprocess
import shlex
import time
import sys
pty_master, pty_slave = pty.openpty()
ngrok_cmd = "./ngrok http 80"
# This doesn't happen for others
# ngrok_cmd = "ls -la"
ngrok = subprocess.Popen(shlex.split(ngrok_cmd), stdin=pty_slave, stdout=pty_slave, stderr=pty_slave)
# It also won't pollute the current terminal when redirected to DEVNULL
# ngrok = subprocess.Popen(shlex.split(ngrok_cmd), stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
print("The subprocess is attached to the pseudo terminal")
print("Its output should not be printed here")
print("Unless I decide to read from pty_master")
print("Checking a few times if the subprocess is done")
for i in range(3):
time.sleep(1)
if ngrok.poll is not None:
print("Subprocess finished")
sys.exit()
print("Don't want to wait any longer.")
# Running the command
python3 ngrok_python.py
预期行为
- 唯一的输出将来自打印语句
-
subprocess具有自定义stdout/err/in。无法访问主终端 - 由于
pty,如果我想了解子进程中发生的情况,我会从pty_master中读取它
实际行为
- 子进程
./ngrok http 80的输出消耗终端
奇怪的是,运行注释掉的部分(ngrok_cmd = "ls -la" 或subprocess with subprocess.DEVNULL)会导致预期的行为。
问题
- 如果为子进程提供的
stdout/err/in已更改,为什么子进程知道如何访问父终端? - 如何在 python 中克服这个问题?
【问题讨论】:
标签: python-3.x linux subprocess pty