13

私は一時ディレクトリを使用しており、プログラムが終了したときに (プログラムが成功したかどうかに関係なく) 確実に削除されるようにしたいと考えています。私はtempfile.mkdtempディレクトリを作成するために使用しており、作成された文字列をそのコマンドstrでディレクトリを削除するサブクラスに入れています:__del__

import shutil
import tempfile

class TempDir(str):
    """ container for temporary directory. 
    Deletes directory when garbage collected/zero references """
    def __del__(self):
        shutil.rmtree(self.__str__(), onerror=my_error_fn)

dbdir = TempDir(tempfile.mkdtemp())

ここに私が確信していないことがあります: プログラムが終了するか、KeyboardInterrupt が発生した場合、Python はすべての変数を自動的に削除/ガベージ コレクションしますか? そうでない場合、ディレクトリが削除されたことを確認するにはどうすればよいですか?

Python でのデストラクタ メソッドの作成に関する関連情報。TempDir オブジェクトが他に何も参照していない限り、それ__del__を破壊するために使用しても問題ないようです。

4

3 に答える 3

19

私は__del__メソッドを使用しません。セマンティクスは信頼できず、ガベージ コレクションに干渉する可能性があります。コンテキスト マネージャーを使用します。and メソッドを定義__enter__し、ステートメント__exit__でオブジェクトを使用します。withそれは明確で、明示的であり、心配することなく機能します。

または、コンテキストマネージャーを作成する別の方法:

@contextlib.contextmanager
def tempdir(prefix='tmp'):
    """A context manager for creating and then deleting a temporary directory."""
    tmpdir = tempfile.mkdtemp(prefix=prefix)
    try:
        yield tmpdir
    finally:
        shutil.rmtree(tmpdir)
于 2012-06-10T00:28:47.253 に答える
9

特定の(セミモックされた)ファイル構造の存在に依存するパッケージテストスイートに似たものが必要でした。多くのテストモジュールでは、どのテストがどの順序で実行されるか、またはテスト実行がどのように終了するかを常に把握しているわけではありません。

私の経験では、アプリケーションの終了時に使用__del__することは信頼できません。また、コンテキストマネージャーを使用するということは、テストファイルを書き直して、すべてが適切にラップされることを確認することを意味します。代わりに。を使用しますatexit<package>.tests.__init__私が追加したばかりです:

import atexit, shutil, tempfile

test_area = tempfile.mkdtemp()
atexit.register(shutil.rmtree, test_area)

その後、Pythonは終了時に呼び出しshutil.rmtree(test_area)ます。必要に応じて、エラー処理のキーワード引数を追加することもできます。

于 2012-12-16T23:42:49.987 に答える
1

プログラムが終了したときにのみすべてを削除します(通常のように)。

説明のために、私が使用したコードは次のとおりです。

import tempfile
import shutil
import os

class TempDir(str):
    """ container for temporary directory. Deletes directory when garbage
    collected/zero references """
    def __del__(self):
        print "deleting temporary files in directory {}".format(self.__str__())
        shutil.rmtree(self.__str__(), onerror=delete_dir_handler)

def delete_dir_handler(listdir_fn, dirname, exception):
    try:
        for fileobj in listdir_fn(dirname):
            os.remove(fileobj)
        os.removedirs(dirname)
    except (AttributeError, OSError, TypeError):
        print exception[1]
        print "Sorry. Couldn't delete directory {}.".format(dirname)
        raise

test = TempDir(tempfile.mkdtemp())

そして出力:

$ python my_file.py
deleting temporary files in directory /var/folders/A9/A9xrfjrXGsq9Cf0eD2jf0U+++TI/-Tmp-/tmpG3h1qD

対話モードで実行すると、プログラムを終了するまで削除されません。

$ python -i my program 
>>> # pressed Ctrl-C here
KeyboardInterrupt
>>> # again, Ctrl-C
KeyboardInterrupt
>>> # Ctrl-D to exit
deleting temporary files in directory /var/folders/A9/A9xrfjrXGsq9Cf0eD2jf0U+++TI/-Tmp-/tmpMBGt5n

最後に、ファイルに行を追加するraw_input('')と、Ctrl-C を押すと、プログラムの終了とまったく同じように動作します。

于 2012-06-10T00:27:29.793 に答える