Python中打开的文件过多

24 投票
3 回答
26486 浏览
提问于 2025-04-16 08:13

我写了一个测试程序,这个程序需要大量使用文件。经过一段时间(大约2小时),我遇到了一个错误:IOError: [Errno 24] Too many open files: '/tmp/tmpxsqYPm'。我仔细检查了所有的文件句柄,确保它们都被关闭了,但错误依然存在。

我尝试用resource.RLIMIT_NOFILE来查看允许打开的文件数量,以及当前打开的文件数量:

def get_open_fds():

    fds = []
    for fd in range(3,resource.RLIMIT_NOFILE):
            try:
                    flags = fcntl.fcntl(fd, fcntl.F_GETFD)
            except IOError:
                    continue

            fds.append(fd)

    return fds

所以如果我运行以下测试:

print get_open_fds()
for i in range(0,100):
    f = open("/tmp/test_%i" % i, "w")
    f.write("test")
    print get_open_fds()

我得到了这个输出:

[]
/tmp/test_0
[3]
/tmp/test_1
[4]
/tmp/test_2
[3]
/tmp/test_3
[4]
/tmp/test_4
[3]
/tmp/test_5
[4] ...

这很奇怪,我原本以为打开的文件数量会逐渐增加。我的脚本是正确的吗?

我在使用Python的日志记录和子进程功能。这可能是导致我文件描述符泄漏的原因吗?

谢谢,
丹尼尔

3 个回答

10

resource.RLIMIT_NOFILE 的值确实是 7,但这只是一个索引,用来从 resource.getrlimit() 这个函数中获取信息,而不是直接的限制值。你需要使用 resource.getrlimit(resource.RLIMIT_NOFILE) 来获取你想要的最大值。

14

修正后的代码是:

import resource
import fcntl
import os

def get_open_fds():
    fds = []
    soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
    for fd in range(0, soft):
        try:
            flags = fcntl.fcntl(fd, fcntl.F_GETFD)
        except IOError:
            continue
        fds.append(fd)
    return fds

def get_file_names_from_file_number(fds):
    names = []
    for fd in fds:
        names.append(os.readlink('/proc/self/fd/%d' % fd))
    return names

fds = get_open_fds()
print get_file_names_from_file_number(fds)
14

你的测试脚本在每次循环时都会重新写入f,这就意味着每次都会关闭这个文件。无论是把信息记录到文件里,还是使用subprocess和管道,这些操作都会占用一些资源,如果用得太多,就可能会用完这些资源。

撰写回答