Слишком много открытых файлов в Python - PullRequest
23 голосов
/ 08 декабря 2010

Я написал своего рода набор тестов, интенсивно использующий файлы.Через некоторое время (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 ]

14 голосов
/ 29 ноября 2012

Исправленный код:

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)
12 голосов
/ 08 декабря 2010

Ваш тестовый скрипт перезаписывает f каждую итерацию, что означает, что файл будет закрываться каждый раз. При ведении журнала в файлы и subprocess с каналами используются дескрипторы, что может привести к исчерпанию.

10 голосов
/ 20 декабря 2010

resource.RLIMIT_NOFILE действительно равен 7, но это индекс для resource.getrlimit (), а не само ограничение ... resource.getrlimit (resource.RLIMIT_NOFILE) - это то, что вы хотите, чтобы ваш top range () был

...