无法使用Popen()可靠地打开子进程 - OSError [Errno 14] Bad Address

时间:2016-04-04 08:32:37

标签: python subprocess

我正在尝试打开多个子进程 - 每个子进程运行相同的预编译二进制文件,但使用subprocess32.Popen()在Python(2.7)下对独特目录中的文件进行操作。大多数情况下工作正常,但我经常得到OSError [Errno 14] Bad Address。这是代码:

self.gld_stdout_file = open('stdout', 'w+')
self.gld_stderr_file = open('stderr', 'w+')
...
subprocess.Popen(string.join(gld_open_str, " "), shell=True, stderr=self.gld_stderr_file,
                 stdout=self.gld_stdout_file, bufsize=-1, close_fds=ON_POSIX,
                 env={'TEMP':temp_path})

这个错误发生在使用Popen()的大约5-10%的尝试中,而在同一个循环中的其他Popen()调用工作正常。环顾四周,似乎这可能来自低级套接字调用中的错误,我不是直接连接。 (例如Herehere

关于我为什么会收到此错误的任何想法?

更重要的是:

我该如何解决?

作为参考,我们使用的是subprocess32,它可以通过多个子进程调用提供更高的稳定性。此外,如果相关,则整个方案被包装到更大的基于MPI的HPC并行调用中,使得多个计算节点试图同时执行相同的操作。由于担心多次尝试执行同一文件可能会遇到冲突或文件系统问题,我们已经在执行之前将二进制文件复制到每个节点。

另外,我在使用shell=False时看到同样的问题:

subprocess.Popen(gld_open_list, shell=False, stderr=self.gld_stderr_file,
                 stdout=self.gld_stdout_file, bufsize=-1, close_fds=ON_POSIX,
                 env={'TEMP':temp_path})

3 个答案:

答案 0 :(得分:1)

这是python2.6上的错误,并修复为2.7。

由于读取系统调用从这些内部返回EINTR而引发IOError  方法(read()readline()readlines())。

请参阅: https://github.com/python/cpython/commit/736ca00270db72fefa5fb278982c96e5e7139d72

https://github.com/python/cpython/blob/2.6/Objects/fileobject.c#L1362

升级你的python然后一切都很有趣。

答案 1 :(得分:0)

似乎与Windows一起发生。没有MacOS的问题。

我找到了一个黑客但实用的解决方案:

while True:
    try:
        proc = subprocess.Popen(cmd, 
                        stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1)
        (output,err)=proc.communicate()
        break
    except:
        log_msg("Exception in spawning subprocess. Retrying ...") 

答案 2 :(得分:0)

我遇到了同样的问题,并设法摆脱了它。我发现仅当代码在集群中的不同节点上运行时,才会发生此问题。如果所有等级都在同一节点中,那么一切都很好。因此,我在系统中尝试过的操作:

  • 在Popen中使用shell=True。有了这个问题,问题并没有解决,但是在我的HPC上发生的可能性要低得多。
  • 使用Anaconda停止。我从那里开始使用mpi4py和Python。
  • 使用Open MPI 4.0.1。我以前使用的是版本3。
  • 制作一个Python virtual environment,并使用pip在其中安装所有必需的工具(mpi4py,NumPy等)。

我不知道这些步骤中哪一个是有用的,但是问题似乎现在已经消失了。