Python子进程:打开文件太多

Vah*_*ili 39 python subprocess

我正在使用子进程调用另一个程序并将其返回值保存到变量.此过程在循环中重复,并在几千次之后程序崩溃并出现以下错误:

Traceback (most recent call last):
  File "./extract_pcgls.py", line 96, in <module>
    SelfE.append( CalSelfEnergy(i) )
  File "./extract_pcgls.py", line 59, in CalSelfEnergy
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
  File "/usr/lib/python3.2/subprocess.py", line 745, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.2/subprocess.py", line 1166, in _execute_child
    errpipe_read, errpipe_write = _create_pipe()
OSError: [Errno 24] Too many open files
Run Code Online (Sandbox Code Playgroud)

任何想法如何解决这个问题非常感谢!

评论提供的代码:

cmd = "enerCHARMM.pl -parram=x,xtop=topology_modified.rtf,xpar=lipid27_modified.par,nobuildall -out vdwaals {0}".format(cmtup[1])
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
out, err = p.communicate()
Run Code Online (Sandbox Code Playgroud)

gog*_*sca 30

在Mac OSX(El Capitan)中查看当前配置:

#ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 256
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 709
virtual memory          (kbytes, -v) unlimited
Run Code Online (Sandbox Code Playgroud)

打开的文件值设置为10K:

#ulimit -Sn 10000
Run Code Online (Sandbox Code Playgroud)

验证结果:

#ulimit -a

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 10000
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 709
virtual memory          (kbytes, -v) unlimited
Run Code Online (Sandbox Code Playgroud)

  • 自 2019 年 10 月(El Capitan 10.11.6)起,`ulimit -a` 的输出看起来略有不同,例如 -n 现在是“文件描述符”而不是“打开文件”`-n:文件描述符`。但是 `ulimit -Sn 50000` 解决了我的问题。谢谢。 (3认同)

Vah*_*ili 16

我想这个问题是因为我正在使用子进程处理一个打开的文件:

cmd = "enerCHARMM.pl -par param=x,xtop=topology_modified.rtf,xpar=lipid27_modified.par,nobuildall -out vdwaals {0}".format(cmtup[1])
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
Run Code Online (Sandbox Code Playgroud)

这里cmd变量包含刚刚创建但未关闭的文件的名称.然后subprocess.Popen在该文件上调用系统命令.执行此操作多次后,程序崩溃并显示该错误消息.

所以我从中学到的信息是

关闭您创建的文件,然后进行处理

谢谢


Mat*_*ney 8

您可以尝试提高操作系统的打开文件限制:

ulimit -n 2048

  • 实际上,该命令不会将限制提高到高于`/ etc/security/limits.conf`中设置的限制.为了提高它,你需要在这个文件中放置像这样的`*soft nofile 4096` /`*hard nofile 4096`这样的行(用你自己的值替换'4096`). (6认同)

Son*_*iku 8

正如其他人所指出的,提高 /etc/security/limits.conf 中的限制以及文件描述符对我个人来说是一个问题,所以我做了

sudo sysctl -w fs.file-max=100000 
Run Code Online (Sandbox Code Playgroud)

并添加到/etc/sysctl.conf:

fs.file-max = 100000
Run Code Online (Sandbox Code Playgroud)

重新加载:

sudo sysctl -p
Run Code Online (Sandbox Code Playgroud)

此外,如果您想确保您的流程不受其他任何东西(我的)的影响,请使用

cat /proc/{process id}/limits 
Run Code Online (Sandbox Code Playgroud)

找出你的进程的实际限制是什么,对我来说,运行 python 脚本的软件也应用了它的限制,这些限制覆盖了系统范围的设置。

在解决了我与此错误有关的特定问题后,在此处发布此答案,希望对某人有所帮助。


jfs*_*jfs 5

由创建的子进程Popen()可能会从父进程继承打开文件描述符(有限资源)。close_fds=True避免在POSIX上使用(Python 3.2以来的默认设置)。另外,“ PEP 0446-使新创建的文件描述符不可继承”处理了一些剩余的问题(自Python 3.4起)


小智 5

也许您多次调用该命令。如果是这样,每次你做的时候stdout=subprocess.PIPE。在每次通话之间尝试做p.stdout.close()


小智 5

使用上下文管理器代替:

cmd = "enerCHARMM.pl -param=x,xtop=topology_modified.rtf,xpar=lipid27_modified.par,nobuildall -out vdwaals {0}".format(cmtup[1])
with subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) as p:
    out, err = p.communicate()
Run Code Online (Sandbox Code Playgroud)

这将在最后一行之后p.stdout关闭。p.stderr

Python中相关代码:https://github.com/python/cpython/blob/208a7e957b812ad3b3733791845447677a704f3e/Lib/subprocess.py#L1031-L1038

相关文档:https://docs.python.org/3/library/subprocess.html#subprocess.Popen