4

メイン プログラムが停止したときに Python スレッドを停止したいと考えています。サーバーに接続するクラス用です。接続はバックグラウンド スレッドによって維持され、フォアグラウンド スレッドはコールバックに応答します。以下は最小限の例です。

#!/usr/bin/python
import time, threading
class test():
    running = False
    def __init__(self):
        print "init"
        self.running = True
        self.thread = threading.Thread(target = self.startThread)
        self.thread.start()

    def __del__(self):
        running = False
        print "del"

    def startThread(self):
        print "thread start"
        while self.running:
            time.sleep(1)
            print "thread running"

a = test()

プログラムが終了すると、バックグラウンド スレッドが停止するように通知されるように __del__() が呼び出されることを素朴に期待しますが、バックグラウンド スレッドが停止するまで i は呼び出されません。一部の関数を明示的に呼び出すことはオプションではありません。クラスは他の人によって使用されているため、余分なコード行を強制的に使用したくないからです。

4

4 に答える 4

1

gnibblerのコメントによると、明示的なリソースの割り当て解除にはコンテキストマネージャーを使用する方がよい場合があります。__del__リソースの割り当て解除に使用する必要があるかどうかによって、意見は異なるようです。このテーマに関するいくつかの良い投稿がここここにあります。

RAIIが使用されるC++のような言語に慣れている場合、通常は参照カウントとガベージの方法が原因で、Pythonのデストラクタが期待どおりに呼び出されない可能性があるという考えに慣れるのが少し難しい場合があります。コレクションは動作します。

したがって、Pythonでの通常のアプローチは、リソースの明示的な割り当て解除を提供するために使用できるコンテキストマネージャーを使用することです。

単純なスレッドの例は次のようになります(テストされていません)。

#!/usr/bin/python
import time, threading

class test():
    def __init__(self):
        print "init"
        self.stop_event = threading.Event()
        self.thread = threading.Thread(target = self.startThread)
        self.thread.start()

    def startThread(self):
        print "thread start"
        while not self.stop_event.isSet():
            time.sleep(1)
            print "thread running"

    def close(self):
        # Request thread to stop.
        self.stop_event.set()
        # Wait for thread to exit.
        self.thread.join()

    def __enter__(self):
        # Nothing to do, thread already started.  Could start
        # thread here to enforce use of context manager.

    def __exit__(self, exc_type, exc_value, traceback):
        self.close()

このtest()クラスは、コンテキストマネージャーで次のように使用されます。

with test():
    # Thread will be active here.
    pass

# Thread will have been stopped and joined.

または、Pythonのcontextlib.closingヘルパー関数を使用してclose、終了時に呼び出されるようにします。

import contextlib

with contextlib.closing(test()):
    # Thread will be active here.
# But not here
于 2013-02-20T11:41:23.837 に答える