You need to enable JavaScript to run this app. 如何使用Popen交互式获取子进程输出并向子进程发送输入?
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Popen交互式获取子进程输出并向子进程发送输入?

问题根源

你的代码卡住核心有3个原因:

  • 子进程缓冲机制问题:OVFTool这类工具检测到标准输出是管道而非交互式终端时,会默认开启块缓冲而非行缓冲,输出内容攒到一定大小才会刷出,你即使flush自己的stdin也读不到子进程还没刷出的提示内容,proc.stdout.flush() 是无效操作,父进程无法主动刷新子进程的输出缓冲区。
  • 换行符适配错误:Windows系统下命令行工具识别的输入结束符是\r\n而非\n,你写入用户名密码时只加了\n,OVFTool会认为你还没完成输入,自然不会输出后续内容。
  • 密码输入场景的特殊处理:绝大多数CLI工具在密码输入阶段不会输出换行符,readline() 会一直等待换行符出现才返回,你后续用固定长度读也会因为子进程没刷缓冲而阻塞。

修复方案

1. 基础修改就能解决大部分情况

调整输入换行符、关闭不必要的参数、改用参数列表传参避免转义问题:

import subprocess
import os
from time import sleep

def export_extract_ova_file():
    vm_name = input("What is the name of the vm you are exporting?")
    print(f"Exporting {vm_name} from VSphere.")
    # 改用参数列表传参,避免shell=True和引号转义问题
    cmd = [
        ovf_tool_path,
        f"vi://example_ip/{vm_name}",
        f"./{vm_name}.ova"
    ]
    with subprocess.Popen(cmd, text=True,
                          stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                          stderr=subprocess.STDOUT, bufsize=0) as proc:
        # 读用户名提示
        proc_read = proc.stdout.readline()
        print(proc_read)
        username = input("Please enter your username")
        # 用os.linesep自动适配系统换行符
        proc.stdin.write(username + os.linesep)
        proc.stdin.flush()

        # 读密码提示
        proc_read = proc.stdout.readline()
        print(proc_read)
        password = input("Please enter your password")
        proc.stdin.write(password + os.linesep)
        proc.stdin.flush()

        # 循环逐字符读后续输出,不会阻塞
        while True:
            char = proc.stdout.read(1)
            if not char:
                # 子进程已退出
                break
            print(char, end='')

2. 极端情况适配

如果上面修改还是卡住,说明OVFTool必须要交互式TTY环境才能正常输出,Windows下可以用winpty封装调用,或者直接用模拟终端的第三方库实现交互,就能完全匹配手动执行时的输出逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 15:21:01