web-dev-qa-db-ja.com

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] ...

奇妙なことに、開くファイル記述子の数が増えると予想していました。私のスクリプトは正しいですか?

私はPythonのロガーとサブプロセスを使用しています。それが私のfdリークの理由でしょうか?

ありがとう、ダニエル

24
dmorlock

テストスクリプトは反復ごとにfを上書きします。これは、ファイルが毎回閉じられることを意味します。ファイルへのログ記録とパイプを使用したsubprocessの両方で記述子が使い果たされ、枯渇につながる可能性があります。

修正されたコードは次のとおりです。

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
dangonfast

resource.RLIMIT_NOFILEは確かに7ですが、これはresource.getrlimit()へのインデックスであり、制限自体ではありません... resource.getrlimit(resource.RLIMIT_NOFILE)は、トップrange()にしたいものです。

10
Peter Buckner