1

Python でオブジェクトをクリーンアップする方法を探していました。私は現在ピピを使用しています。

Web ページと例を見つけました。

まず基本的な例:

class FooType(object):
    def __init__(self, id):
        self.id = id
        print self.id, 'born'

    def __del__(self):
        print self.id, 'died'


ft = FooType(1)

これは印刷すべきです:

1人生まれ 1人死亡

しかし、それは単に生まれて1を印刷します

だから私の質問は: PyPy で何かをクリーンアップするにはどうすればよいですか?

4

3 に答える 3

4

CPython を含む他のすべての Python 実装で行う必要があるのと同じ方法: 自動メモリ管理と.__del__

__del__CPython でさえ、がまったく呼び出さないケースが 1 つ以上あり、予想よりもかなり遅れて呼び出されるケースがかなりあります (たとえば、任意のオブジェクトが参照サイクルに巻き込まれた場合、これは非常に簡単に発生する可能性があります)。 )。つまり、おそらく有効期間の問題をデバッグする場合 (ただし、そのためのメモリ プロファイラがあります!) と、一部のコードが明示的にクリーンアップを怠った場合の最後の手段を除いて、本質的に役に立たないことを意味します。

クリーンアップについて明確にすることで、これらすべての問題を回避できます。クリーンアップを行うメソッドを用意し、クライアント コードが適切なタイミングでそれを呼び出せるようにします。コンテキスト マネージャーを使用すると、例外が発生した場合にこれを正しく処理しやすくなり、読みやすくなります。多くの場合、参照カウントが「すぐに」 を呼び出す場合__del__でも、よりも早くクリーンアップできます。たとえば、次のようになります。__del__

def parse_file(path):
    f = open(path)
    return parse(f.read()) # file stays open during parsing

この wrt リソース使用量よりも悪い:

def parse_file(path):
    with open(path) as f:
        s = f.read()
    # file is closed here
    return parse(s)

また、リソース ラッパー オブジェクトの有効期間とラップされたリソースの有効期間を混同しないため、このような設計はよりクリーンであると主張します。場合によっては、そのオブジェクトをリソースよりも長く存続させたり、新しいリソースの所有権を取得したりすることが理にかなっている場合があります。

于 2013-02-10T18:49:58.960 に答える
4

特定の時間に確実に「クリーンアップ」を実行する必要がある場合は、コンテキスト マネージャーを使用します。

class FooType(object):
    def __init__(self, id):
        self.id = id
        print 'born'
    def __enter__(self):
        print 'entered'
        return self
    def __exit__(self, *exc):
        print 'exited'

with FooType(1) as ft:
    pass # do something with ft
于 2013-02-10T18:48:18.303 に答える
2

あなたの例で__del__は呼び出されませんが、それはあなたが書いたテストプログラムがすぐに終了するためです。__del__PyPyは、オブジェクトに到達できなくなった後しばらくして が呼び出されることを保証しますが、それはプログラムが実行を継続している間だけです。したがってft = FooType(1)、無限ループで実行すると、しばらくしてから出力されdiedます。

他の回答が説明しているように、CPython は実際には何も保証しませんが、単純なケース (参照サイクルがないなど) では、__del__すぐに確実に呼び出します。それでも、ポイントは、これに厳密に依存するべきではないということです。

于 2013-02-15T09:29:07.923 に答える