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

为何subprocess.Popen调用grep远快于check_output?该如何选型?

为什么用subprocess.Popen()调用grep比subprocess.check_output()快这么多?

嘿,先给你指出一个关键问题:你看到的耗时差异根本不是两种方法的真实性能差距——你的Popen代码其实根本没等grep执行完!这才是耗时差了几千倍的核心原因。

问题出在你的代码里

先看你写的Popen片段:

matched_reads = subprocess.Popen(['grep', match, file], stdout=subprocess.PIPE, env=myenv)
mathced_reads = str(matched_reads).splitlines()

subprocess.Popen是非阻塞调用——它启动grep进程后立刻返回一个进程对象,不会等grep把文件处理完。你接下来直接把这个进程对象转成字符串,这根本不是读取grep的输出,只是把进程的描述信息(比如<subprocess.Popen object at 0x...>)拆成了行,完全没处理实际的匹配结果。这也是为什么耗时只有0.002秒:你根本没等grep干活!

而subprocess.check_output是阻塞调用,它会全程等待grep进程执行完毕,把所有匹配结果捕获后才返回,所以5.28秒才是grep处理你的大文件的真实耗时。

正确的Popen用法应该是这样

如果你想用Popen并正确获取grep的输出,必须等待进程结束并读取它的标准输出,比如用communicate()方法:

start = time.time()
match = 'chr3' + "[[:space:]]"
# 启动进程
proc = subprocess.Popen(['grep', match, file], stdout=subprocess.PIPE, env=myenv)
# 等待进程执行完成,同时获取输出
matched_reads, _ = proc.communicate()
# 把bytes类型的输出转成字符串,再拆分成行
matched_reads = matched_reads.decode().splitlines()
end = time.time()
runtime = end-start
print("Popen Grep (correct): ", runtime)

这样修改后,Popen的耗时会和check_output差不多,因为它现在会老老实实等grep处理完文件了。

该选哪种方法?

  • 如果你只是想简单捕获命令输出,并且希望命令执行出错(比如grep没找到匹配返回非0码)时直接抛出异常,优先选subprocess.check_output()——它封装了启动、等待、捕获输出的全流程,代码更简洁易读,不用自己处理进程等待的逻辑。
  • 如果你需要更灵活的控制,比如:
    • 边运行grep边读取输出(不用等整个文件处理完)
    • 同时处理标准输入/输出/错误流
    • 启动进程后先去做别的任务,稍后再处理结果
      那可以用subprocess.Popen(),但一定要记得用communicate()或者wait()方法等待进程结束,避免出现逻辑错误。

另外,注意不管用哪种方法,check_output和communicate()返回的都是bytes对象,需要用.decode()转成字符串后再拆分行,这样才能得到你需要的每行字符串。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:53:30