首页 > 解决方案 > 发送 stdout 和 stderr 而不等待进程结束

问题描述

如果我设置 command1 = "start notepad.exe" 有没有办法让脚本输出 gino.stdout 和 gino.stderr 而无需等待 notepad.exe 关闭?

import socket
import subprocess
import os

HOST = '//' # 
PORT = 8081 # 
server = socket.socket()
server.bind((HOST, PORT))
# print('[+] Server Started')
# print('[+] Listening For Client Connection ...')
server.listen(1)
client, client_addr = server.accept()
# print(f'[+] {client_addr} Client connected to the server')

while True:
    command = client.recv(4096)
    command1 = command.decode()
    print(command1)
    if command1 != "exit":
       gino = subprocess.run(command1, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
       risposta = gino.stdout + gino.stderr
       if risposta != b"":
          client.send(risposta)
          print(risposta)
       else:
          v = "Executed " + command1
          print(v)
          client.send(v.encode())
    else:
       client.close()
       sys.exit()

标签: pythonsubprocess

解决方案


令我惊讶的是,这比我预期的要难。我假设notepad.exe是你的命令,我假设你在 Windows 上,所以像这样stdbuf的工具不可用。

从刷新标准输出的程序中获取输出很容易:

# tesflush.py
import time
from sys import stdout

for i in range(100):
    print(f"line {i}")
    stdout.flush()
    time.sleep(0.1)
import subprocess
from time import sleep

p = subprocess.Popen(
    ["python", "testflush.py"], stdout=subprocess.PIPE, encoding="utf8"
)

for line in iter(p.stdout.readline, ""):
    print(line, end="")

但是,如果应用程序不刷新标准输出,生活就有点困难了。我最终偶然发现了这个问题,其中提到了使用pexpect作为获取伪 tty 并因此强制输出刷新的简单方法:

#testnoflush.py
import time

for i in range(100):
    print(f"line {i}")
    time.sleep(0.1)
import pexpect

child = pexpect.spawn("python test2.py", encoding="utf8")
for line in child:
    print(line, end="")
child.close()

我怀疑你会需要这样的东西(如果你真的需要避免,链接的问题有一个手动实现pexpect。)


推荐阅读