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

为何使用subprocess.run()调用eumdac.exe时程序出现冻结?

问题:subprocess.run()调用eumdac.exe时程序冻结

现象

使用以下代码调用eumdac.exe时程序出现冻结:

import subprocess
subprocess.run('eumdac.exe')

在cmd.exe中直接运行eumdac则能正常输出帮助信息:

(project_directory)>eumdac
usage: eumdac [-h] [--version] [--set-credentials ConsumerKey ConsumerSecret] [--debug]
              {describe,search,download,subscribe,tailor} ...

EUMETSAT Data Access Client

positional arguments:
  {describe,search,download,subscribe,tailor}
    describe            describe a collection or product
    search              search for products at the collection level
    download            download product(s) from a collection
    subscribe           subscribe a server for a collection
    tailor              tailoring product(s) from collection

optional arguments:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  --set-credentials ConsumerKey ConsumerSecret
                        permanently set consumer key and secret and exit, see https://api.eumetsat.int/api-key
  --debug               show backtrace for errors

尝试subprocess.run('cmd /c eumdac.exe')也无法解决冻结问题。

原因

subprocess.run()默认会捕获子进程的stdout和stderr,当子进程输出内容填满缓冲区,而父进程未读取这些输出时,会形成死锁:子进程阻塞等待输出被读取,父进程则等待子进程结束。eumdac.exe运行时输出的帮助信息会触发这个问题。

解决方案

可以通过以下几种方式解决:

1. 直接将子进程输出重定向到当前终端

如果不需要捕获输出,让子进程输出直接显示在终端:

import subprocess
import sys

subprocess.run('eumdac.exe', stdout=sys.stdout, stderr=sys.stderr, shell=True)

2. 捕获输出并处理

如果需要获取子进程输出,使用capture_output=True或communicate()读取输出:

import subprocess

# 方式1:用run直接捕获
result = subprocess.run('eumdac.exe', capture_output=True, text=True, shell=True)
print(result.stdout)

# 方式2:用Popen+communicate
proc = subprocess.Popen('eumdac.exe', stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True)
stdout, stderr = proc.communicate()
print(stdout)

3. 显式指定shell并处理管道

Windows环境下,显式开启shell=True配合输出管道配置,避免死锁:

import subprocess

subprocess.run('eumdac.exe', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

关键提示

  • 调用会产生输出的程序时,务必处理stdout/stderr,避免缓冲区溢出导致死锁
  • communicate()方法会读取子进程所有输出直到其结束,是避免死锁的可靠方式
  • 如果子进程需要用户输入,还需配置stdin=subprocess.PIPE,并通过communicate()传入输入内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 14:45:27