2

とても奇妙なものを見つけました。以下のこのショートコードを参照してください。

import os

class Logger(object):
    def __init__(self):
        self.pid = os.getpid()
        print "os: %s." %os

    def __del__(self):
        print "os: %s." %os

def temp_test_path():
    return "./[%d].log" %(os.getpid())

logger = Logger()

これは、説明を目的としています。インポートされたモジュールosを、クラスの委託と破棄について出力するだけです(名前は気にしないでLoggerください)。ただし、これを実行すると、モジュールはクラスデストラクタでos「消える」ように見えます。None以下は出力です。

os: <module 'os' from 'C:\Python27\lib\os.pyc'>.
os: None.

私の問題はどこにあると言われos: None.ていますか。最初の出力行と同じである必要があります。ただし、上記のPythonコードの関数を振り返ってくださいtemp_test_path()。この関数の名前を少し変更して、たとえばtemp_test_pat()、残りのすべてのコードをまったく同じにして実行すると、期待どおりの出力が得られます(以下を参照)。

os: <module 'os' from 'C:\Python27\lib\os.pyc'>.
os: <module 'os' from 'C:\Python27\lib\os.pyc'>.

バグであることを除いて、これについての説明は見つかりません。あなたはできる?ちなみに私はWindows764ビットを使用しています。

4

4 に答える 4

4

インタプリタのシャットダウンに依存して呼び出しを行っている場合は、呼び出される前にモジュールがすでに削除されている__del__可能性があります。コードで明示的にを実行して、少しの間スリープしてみてください。これにより、コードが期待どおりに機能することが明確に示されます。os__del__del logger

また、CPython実装で呼び出されることが保証されていない公式ドキュメントのこのメモにリンクしたいと思います。__del__

于 2013-02-20T16:01:08.033 に答える
4

これを再現しました。確かに面白い行動。理解する必要があることの1つは__del__、インタープリターの終了時に呼び出されることが保証されていないことです。また、インタープリターの終了時にオブジェクトをファイナライズするための指定された順序はありません。

インタプリタを終了するため、os最初に削除されていないという保証はありません。この場合、実際にはオブジェクトosの前にファイナライズされているようです。Loggerこれらのことは、辞書の順序によってはおそらく起こります。globals

終了する直前にグローバルディクショナリのキーを出力する場合:

for k in globals().keys():
    print k

わかるでしょ:

temp_test_path
__builtins__
__file__
__package__
__name__
Logger
os
__doc__
logger

また:

logger
__builtins__
__file__
__package__
temp_test_pat
__name__
Logger
os
__doc__

logger特にリストのどこに座っているかと比較して、あなたがどこに座っているかに注意してくださいos。を使用temp_test_patすると、実際には最初loggerにファイナライズされるため、意味のあるものにバインドされます。ただし、を使用する場合は、Lastをファイナライズします。ostemp_test_path

インタープリターが終了するまでオブジェクトをライブにすることを計画していて、実行したいクリーンアップコードがある場合は、を使用して実行する関数をいつでも登録できますatexit.register

于 2013-02-20T16:05:35.347 に答える
3

他の人があなたに答えを与えました、それはグローバル変数(、、など)がシャットダウン中にモジュールの名前空間から削除される順序が定義されていosませLoggerlogger

ただし、回避策が必要な場合はos、ファイナライザーのローカル名前空間にインポートするだけです。

def __del__(self):
    import os
    print "os: %s." %os

モジュールはこのos時点でまだ存在します、それはあなたがそれへのあなたのグローバルな参照を失ったということだけです。

于 2013-02-20T16:13:35.503 に答える
2

これは予想されることです。Python言語リファレンスから:

また、モジュールの削除に応答してdel()が呼び出された場合(たとえば、プログラムの実行が行われた場合)、del()メソッドによって参照される他のグローバルはすでに削除されているか、破棄されている可能性があります(例:輸入機械のシャットダウン)。

大きな赤い警告ボックスで:-)

于 2013-02-20T16:01:23.647 に答える