Подтвердить что ты не робот

Слишком много открытых файлов в python

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

Что странно, я ожидал увеличения количества открытых файловых дескрипторов. Правильно ли мой script?

Я использую python logger и подпроцесс. Может ли это быть причиной моей утечки fd?

Спасибо, Daniel

4b9b3361

Ответ 1

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

Ответ 2

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

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)

Ответ 3

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