今日、私はインポートされたモジュールを使用するオブジェクトのメソッドについてこの質問をしました。__del__()
問題は__del__()
、モジュールを利用したいということでしたos
が、モジュールがすでに削除されている場合があります(常にではありません)。Pythonプログラムが終了すると、オブジェクトとモジュールが削除される順序はランダムであり、未定義である可能性があると言われました。ただし、私のアプリケーションでは、モジュール(オブジェクトがインスタンス化されている)が削除される前に、オブジェクト(作成したクラスのインスタンス)が削除されていることを確認する必要があります。これを行う方法はありますか?
2 に答える
前に言ったように__del__
、インタプリタが終了するときに呼び出されることに頼るべきではありません。これを適切に行うには、次の2つのオプションがあります。
最初はatexit
import os
import atexit
class Logger(object):
def on_exit(self):
print "os: %s." % os
logger = Logger()
atexit.register(logger.on_exit)
これにより、ロガーが終了時に確実にファイナライズされます。
*問題をもう少し詳しく読むと、インスタンスのクラスを定義するモジュールに単一のインスタンスをバインドすることを計画しているため、全体のコンテキストにとどまる方法がないため、以下のコンテキストマネージャーソリューションはこれでは機能しませんプログラムの実行。を使用する必要がありますatexit.register
。ただし、プログラム設計の観点からはatexit.register
、コードを再構築してリソースを管理するよりも、コンテキストマネージャーを使用してリソースを管理する方がはるかに好きです。
それを行う2番目の(より良い*)方法は、コンテキストを終了するときにクリーンアップコードを実行するコンテキストマネージャーをクラスにすることです。その場合、コードは次のようになります。
import os
class Logger(object):
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
print "os:",str(os)
with Logger() as logger:
#do something ...
キーワードパラメータを使用して関数への参照を添付します。
import os
class Logger(object):
def __del__(self, os=os):
print "os: %s." %os
または、クラス属性にバインドします。
import os
class Logger(object):
def __init__(self):
self.os = os
def __del__(self):
print "os: %s." % self.os
ローカル(十分な)参照を作成することにより、Pythonはos
グローバルとしてではなく、インスタンスまたは関数自体とともにそれぞれ格納されるローカル参照を使用して検索します。
グローバルは実行時にルックアップされ(これが__del__
、他の質問の関数os
がすでにクリーンアップされている場合に失敗する理由です)、ローカル関数は関数オブジェクトと一緒に、またはインスタンス属性の場合はインスタンスとともにクリーンアップされます。