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

如何通过PID连接已启动的Python子进程并获取其标准输出?

如何通过PID获取已启动进程的标准输出?

首先提一句,你当前的nmap命令参数有问题:['nmap', '-', '-oX', '192.168.19.159']里的-是无效参数,应该替换成实际的扫描参数(比如-sS),不过这不是核心问题。

回到你的需求:已经启动的进程的标准输出,默认情况下无法被外部Python脚本直接获取,尤其是在Windows环境下(你用了cmd的tasklist,推测是Windows),进程的IO句柄是私有资源,除非创建时特意做了可继承配置或者预先用IPC机制规划了输出路径。

下面分两种场景给你解决方案:

场景1:还能重新启动目标进程

这是最稳妥的方案,启动时直接把stdout定向到临时文件或者命名管道,后续脚本直接读取即可:

临时文件方案

import subprocess
import tempfile

# 创建临时文件存储输出(delete=False避免进程未结束就被删除)
with tempfile.NamedTemporaryFile(mode='w+', encoding='utf-8', delete=False) as temp_out:
    # 修正后的nmap命令,把XML输出打印到stdout再写入临时文件
    p = subprocess.Popen(
        ['nmap', '-sS', '192.168.19.159', '-oX', '-'],
        stdout=temp_out
    )
    temp_path = temp_out.name

# 后续独立脚本读取这个临时文件
with open(temp_path, 'r', encoding='utf-8') as f:
    nmap_output = f.read()
    print(nmap_output)

命名管道方案(实时读取)

如果需要实时获取输出,可以用Windows的命名管道:

# 启动进程的脚本
import subprocess
import win32pipe
import win32file

# 创建命名管道
pipe_name = r'\\.\pipe\nmap_output'
pipe_handle = win32pipe.CreateNamedPipe(
    pipe_name,
    win32pipe.PIPE_ACCESS_OUTBOUND,
    win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT,
    1, 65536, 65536, 0, None
)

# 启动nmap,把stdout定向到管道
subprocess.Popen(
    ['nmap', '-sS', '192.168.19.159', '-oX', '-'],
    stdout=pipe_handle
)

# 后续读取脚本
def read_nmap_pipe(pipe_name):
    handle = win32file.CreateFile(
        pipe_name,
        win32file.GENERIC_READ,
        0, None,
        win32file.OPEN_EXISTING,
        0, None
    )
    while True:
        try:
            data = win32file.ReadFile(handle, 4096)
            print(data[1].decode('utf-8'), end='')
        except:
            break

read_nmap_pipe(r'\\.\pipe\nmap_output')

场景2:进程已经启动,无法重启

这种情况只能尝试通过Windows API获取进程的stdout句柄,需要用pywin32库,成功率不高,因为依赖句柄权限和原进程的配置:

  1. 先安装依赖:pip install pywin32
  2. 编写读取脚本:
import win32api
import win32process
import win32file
import win32con

def read_process_stdout(pid):
    try:
        # 打开目标进程(需要足够权限)
        proc_handle = win32api.OpenProcess(win32con.PROCESS_ALL_ACCESS, False, pid)
        # 获取标准输出句柄
        stdout_handle = win32process.GetStdHandle(proc_handle, win32process.STD_OUTPUT_HANDLE)
        # 读取输出缓冲区
        _, output_bytes = win32file.ReadFile(stdout_handle, 4096)
        return output_bytes.decode('utf-8', errors='ignore')
    except Exception as e:
        return f"读取失败: {str(e)}"

# 替换成你的nmap进程PID
target_pid = 12345
print(read_process_stdout(target_pid))

注意事项

  • 如果原进程的stdout是控制台窗口,读取到的是控制台缓冲区内容,可能包含多余的控制台输出
  • 权限不足会直接报错,需要以管理员身份运行脚本
  • 如果原进程创建时没有设置stdout句柄可继承,这个方法会失败

为什么psutil/subprocess解决不了?

  • subprocess只能管理自己创建的进程,没有接口连接外部已启动的进程
  • psutil可以获取进程的基本信息、内存/CPU占用,但无法直接读取外部进程的IO流——这涉及到系统级的句柄权限隔离,不是库能直接解决的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 03:28:14