【问题标题】:subprocess32.Popen crashes (cpu 100%)subprocess32.Popen 崩溃(cpu 100%)
【发布时间】:2016-09-30 08:28:17
【问题描述】:

我一直在尝试使用subprocess32.Popen,但这会导致我的系统崩溃(CPU 100%)。所以,我有以下代码:

import subprocess32 as subprocess

for i in some_iterable:
    output = subprocess.Popen(['/path/to/sh/file/script.sh',i[0],i[1],i[2],i[3],i[4],i[5]],shell=False,stdin=None,stdout=None,stderr=None,close_fds=True)

在此之前,我有以下内容:

import subprocess32 as subprocess
for i in some_iterable:
    output subprocess.check_output(['/path/to/sh/file/script.sh',i[0],i[1],i[2],i[3],i[4],i[5]])

.. 我对此没有任何问题 - 只是速度太慢了。

使用 Popen,我发现这很快 - 但我的 CPU 在几秒钟内就超过 100%,系统崩溃了 - 强制重新启动。

我想知道我在做什么导致 Popen 崩溃?

在 Linux 上,Python2.7 如果有帮助的话。

谢谢。

【问题讨论】:

  • 您的脚本到底在做什么,在这种情况下some_iterable 有多大? check_output() 等待每个进程完成,Popen() 没有,所以你正在产生多个并行进程。因此,如果您的脚本消耗大量资源(内存不足),这可能是系统变得不稳定的原因。
  • some_iterable 大约有 200 万个条目。我明白你在说什么,但我该如何避免这种情况?

标签: bash python-2.7 subprocess


【解决方案1】:

问题是您试图一次启动 2 百万个进程,这会阻塞您的系统。

一种解决方案是使用池来限制一次可以运行的最大进程数,并等待每个进程完成。对于这种您正在启动子进程并等待它们(IO 绑定)的情况,multiprocessing.dummy 模块中的线程池可以:

import multiprocessing.dummy as mp
import subprocess32 as subprocess

def run_script(args):
    args = ['/path/to/sh/file/script.sh'] + args
    process = subprocess.Popen(args, close_fds=True)
    # wait for exit and return exit code
    # or use check_output() instead of Popen() if you need to process the output.
    return process.wait()

# use a pool of 10 to allow at most 10 processes to be alive at a time
threadpool = mp.Pool(10)

# pool.imap or pool.imap_unordered should be used to avoid creating a list
# of all 2M return values in memory
results = threadpool.imap_unordered(run_script, some_iterable)
for result in results:
    ... # process result if needed

我忽略了Popen 的大部分参数,因为无论如何您都在使用默认值。如果您的脚本正在执行计算工作,如果它主要执行 IO(网络访问、写入文件等),那么池的大小可能应该在您可用 CPU 内核的范围内,那么可能更多。

【讨论】:

  • 如何在threadpool.imap_unordered(run_script, some_iterable) 中将参数传递给run_script?其次,我使用 csv 阅读器读取 200 万个条目,并且我有类似 `reader = csv.reader(open(filex),delimiter='|') for row in reader:` 在这种情况下 some_iterable是?以前,我将每个 row 传递给 Popen 进程。不知道我现在如何用你的想法实现这一点。
  • 我试图在这里实现这个:pastebin.com/jKka6cHG 但是ofcoz这是错误的......不知道如何用runscript调用threadpool......
  • map 函数需要运行一个函数和一个可迭代的参数,并为列表中的每个项目调用该函数。所以你不需要在循环中调用函数,你可以将reader作为参数迭代器传递,比如this
猜你喜欢
  • 2015-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-29
  • 1970-01-01
  • 2020-12-07
  • 2016-01-21
  • 1970-01-01
相关资源
最近更新 更多