我在一个循环(超过 10 000 次)中使用 subprocess.run
来调用一些 java 命令。
像这样:
import subprocess
import tempfile
for i in range(10000):
ret = subprocess.run(["ls"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
(_, name) = tempfile.mkstemp()
with open(name, 'w+') as fp:
fp.write(ret.stdout.decode())
但是,过了一段时间,我得到了以下异常:
Traceback (most recent call last):
File "mwe.py", line 5, in <module>
ret = subprocess.run(["ls"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
File "/usr/lib/python3.5/subprocess.py", line 693, in run
with Popen(*popenargs, **kwargs) as process:
File "/usr/lib/python3.5/subprocess.py", line 947, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.5/subprocess.py", line 1454, in _execute_child
errpipe_read, errpipe_write = os.pipe()
OSError: [Errno 24] Too many open files
我是否缺少关闭某些文件描述符的内容? 谢谢
最佳答案
mkstemp
返回一个已经打开 文件描述符 fd
后跟文件名。您忽略了文件描述符(您选择的名称 _
表明您已明确选择忽略它),因此您忽略了关闭它。相反,您使用文件名第二次打开文件,创建一个文件对象,其中包含同一文件的第二个 文件描述符。无论您是否关闭第二个,第一个都会保持打开状态。
这是对 mkstemp
方法的修复:
temporaryFiles = []
for i in range(1000):
...
fd, name = tempfile.mkstemp()
os.write(fd, ... )
os.close(fd)
temporaryFiles.append(name) # remember the filename for future processing/deletion
根据 Wyrmwood 在评论中的建议,更好的方法是:
temporaryFiles = []
for i in range(1000):
...
with tempfile.NamedTemporaryFile(delete=False) as tmp:
# tmp is a context manager that will automatically close the file when you exit this clause
tmp.file.write( ... )
temporaryFiles.append(tmp.name) # remember the filename for future processing/deletion
请注意,mkstemp
和 NamedTemporaryFile
构造函数都有参数,可让您更具体地了解文件的位置 (dir
) 和命名(前缀
,后缀
)。如果您想保留这些文件,您应该指定 dir
以便将它们保留在默认临时目录之外,因为默认位置可能会被操作系统清理。
关于python - mkstemp 打开太多文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54150644/