You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用subprocess运行命令时如何无需等待进程结束即可获取stdout与stderr

原因说明

subprocess.run() 本身为阻塞调用,必须等待目标进程执行结束后才会返回stdout、stderr结果,所以你启动记事本这类不会自动退出的进程时,程序会一直阻塞在该调用位置。

解决方法

替换subprocess.run()为非阻塞的subprocess.Popen()接口,该接口调用后会立刻返回进程对象,不需要等待进程结束,你可以自行控制输出读取、进程状态检查逻辑。

代码修改参考

首先修正原代码缺失的import sys导入,再调整命令执行部分的逻辑:

import socket
import subprocess
import os
import sys # 原代码缺失该导入,执行exit逻辑会报错

HOST = '0.0.0.0' # 原HOST填写错误,修正为监听所有网卡的标准写法
PORT = 8081
server = socket.socket()
server.bind((HOST, PORT))
server.listen(1)
client, client_addr = server.accept()

while True:
    command = client.recv(4096)
    command1 = command.decode().strip()
    print(command1)
    if command1 != "exit":
        # 替换run为Popen,不等待进程结束
        proc = subprocess.Popen(
            command1,
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            close_fds=True
        )
        # 可选:如果不需要等待输出,直接返回执行提示,后续异步处理输出
        # 注意:记事本等GUI程序本身没有stdout/stderr输出,无法拿到返回内容
        try:
            # 等待1秒获取输出,如果进程没结束也直接返回
            stdout, stderr = proc.communicate(timeout=1)
            risposta = stdout + stderr
        except subprocess.TimeoutExpired:
            # 进程还在运行,返回启动成功提示
            risposta = f"命令 {command1} 已启动,进程ID: {proc.pid}\n".encode()
        
        if risposta != b"":
            client.send(risposta)
            print(risposta)
        else:
            v = "Executed " + command1
            print(v)
            client.send(v.encode())
    else:
        client.close()
        sys.exit()

注意事项

  • 如果你执行的是start notepad.exe这类命令,start是Windows cmd内置命令,它本身会启动独立的子进程,你捕获到的只是start命令的输出,而非记事本的输出;且记事本是GUI程序,默认没有标准输出和标准错误输出,无论用什么方式都拿不到它的输出内容
  • 如果需要实时获取长时间运行的命令行程序(如持续ping、日志监听脚本)的输出,需要单独开启线程读取proc.stdout和proc.stderr流,避免缓冲区被占满导致进程卡住
  • 远程执行命令存在严重安全风险,仅可在本地测试或可信环境下使用

内容的提问来源于stack exchange,提问作者Narrow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 03:00:00