1

最近、サーバーで「開いているファイルが多すぎます」という例外が発生しました。私は lsof をチェックしましたが、確かに、開いたままの PDF ファイルがたくさんあります (すべて同じディレクトリにあります)。この特定のファイルは、Django FileField を通じて管理されます。プロジェクト内でファイルを名前で明示的に開いている場所を追跡しようとしましたが、見つけることができる場所は1つだけであり、そこからファイルが正しく閉じられていることがわかります。ファイルが開いたままになっている場所は他にもあるかもしれませんが、実際にファイルを開いたままにしているコードを見つける方法がわかりません。open() と file() の呼び出しを単純に grep しようとしましたが、うまくいきませんでした。

ファイルを開いたままにするコード行を体系的に追跡する方法はありますか?

編集: ファイルを適切に開いたり閉じたりする方法を理解しています。私の質問は、ファイルを開いたままにしておく既存のコード行を追跡する方法があるかどうかです。

4

2 に答える 2

4

を使用する場合はopen、コンテキスト マネージャーとして使用してみてください。そうすれば、何が起こっても、作業が完了すると閉じられます。

with open('file.txt', 'r') as fin:
    # Access fin like normal

# No matter what happens, after the block, it's closed!

open別の方法として、 andのインスタンスを、close追加のロギングを行う独自の関数に置き換えることもできます。

def my_open(filename, *args):
    logger.debug('Opening %s' % filename)
    return open(filename, *args)

def my_close(file_obj):
    logger.debug('Closing %s' % file_obj.name)
    return file_obj.close()

最後の手段として、問題のコードにアクセスできない場合、またはコードを変更するのが面倒な場合は、関数にモンキー パッチを適用してみてください。

import traceback
class MyFile(file):
    @staticmethod
    def open(*args, **kwargs):
        return MyFile(*args, **kwargs)

    def __init__(self, *args, **kwargs):
        self._file = self._open(*args, **kwargs)
        print('Opening %s from %s' % (
            self._file.name, ''.join(traceback.format_stack())))

    def close(self):
        print('Closing file %s from %s' % (
            self._file.name, ''.join(traceback.format_stack())))
        self._file.close()

# Now the monkey-patching
file = MyFile
MyFile._open = open
open = MyFile.open

o = open('hello', 'w+')

これは確かに世界で最も美しいものではありませんが、モンキー パッチを適用できれば、少なくともレガシー コードを処理することができます。

于 2013-05-10T17:35:45.503 に答える