【问题标题】:Segmentation fault (core dumped) when trying to use subprocess in python尝试在 python 中使用子进程时出现分段错误(核心转储)
【发布时间】:2018-08-28 18:12:23
【问题描述】:

我正在尝试多次并行运行程序(使用不同的参数)。我在网上搜索,发现python中的subprocess是一个很好的方法。我的代码如下:

import subprocess
import os

models_path="~/"
procs = []
num_of_procs_running=0
i = 0
for model_name in os.listdir(models_path):
    if num_of_procs_running > num_of_procs:
        for p in procs:
            p.wait()
        procs = []
        num_of_procs_running = 0
    elif model_name.endswith(".onnx"):
        name, ending = model_name.split(".")
        runner = './SOME_PROGRAM '+str(i)+'> output.txt'
        i+=1
        procs.append(subprocess.Popen(runner,shell=True))
        num_of_procs_running += 1
        print("Total processes:",num_of_procs_running)
        print("\n")
for p in procs:
    p.wait()

如果我尝试运行超过 56 个子进程,我会遇到分段错误(核心转储)。我的机器有 56 个 CPU,每个 CPU 有 12 个内核。如何运行超过 56 个子进程,或者使用线程? 谢谢。

【问题讨论】:

  • 调试的第一步需要找到一种在直接运行MY_PROGRAM 可执行文件时可靠地触发段错误的方法。然后启动一个调试器(例如gdb),看看它为什么会崩溃。你的 Python 代码不是这里的问题——问题出在 MY_PROGRAM 不知何故。
  • 顺便说一句:不要使用shell=True,尤其是当您像这样手动组装参数时。只需直接传递参数列表即可。
  • 您是否有理由不使用nameending
  • @DavidCullen 是的。它正在我的原始代码中使用。这篇文章没有必要。它是发送给程序的参数之一。
  • @GuyOhayon:通常你应该避免在一个字符串中传递参数。为什么要启动一个完整的单独进程(shell)来为您将字符串解析为字符串列表?而且,如果您不小心错误地组装了字符串,shell 可能会执行您没想到的任意命令,而如果您传递字符串列表,则不会发生这种情况。但是解决您的其他评论:您可以在两种情况下重现 exactly 相同的命令行吗?您能否尝试以其他方式重现环境(匹配环境变量、重定向或关闭标准输入/标准输出等)?

标签: python python-3.x subprocess


【解决方案1】:
  1. @danielpryden 已经 suggested 不要调用 shell:

    import subprocess
    
    # bad (mocking your code)
    p = subprocess.Popen("echo 1 > output.txt", shell=True)
    p.wait()
    
    # better
    fp = open("output.txt", "w")
    p = subprocess.Popen(["echo", "1"], stdout=fp)
    
    p.wait() # or do something else
    fp.close() # remember to close file
    
  2. 当达到最大线程数时,它会一直等到所有个线程完成,效率很低。你似乎试图实现的正是multiprocessing.pool.Pool 所做的:

    from multiprocessing.pool import Pool
    
    # mocking your code
    modules = ["mod1.onnx", "mod2.onnx"]
    
    def run(module):
      print("running", module)
    
    # use the maximum number of threads by default
    with Pool() as pool:
      pool.map(run, modules)
    
  3. 分段错误不是由您的 Python 应用程序引起的,而是由您尝试执行的任何程序引起的。如果是 C++,请查看 std::thread::hardware_concurrency;您需要更改程序代码而不是您的 python 脚本。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-18
  • 1970-01-01
  • 2018-10-13
  • 1970-01-01
  • 2021-12-20
  • 2020-10-30
相关资源
最近更新 更多