一種方式是通過使Thread
子也context manager。這將有效地使__exit__()
您想要觸發的特殊方法。
下面顯示了我提議的內容。注意:我將property
參數重命名爲傳遞構造函數,因爲property
是內置Python的名稱。
from threading import Thread
import time
TEST_THREAD_EXCEPTION = False # change as desired
class MyThread(Thread):
def __init__(self, attribute):
Thread.__init__(self)
self.attribute = attribute
def cleanup(self):
# Clean up here
print(' cleaning up after thread')
def run(self):
if TEST_THREAD_EXCEPTION:
raise RuntimeError('OOPS!') # force exception
print(' other thread now running...')
time.sleep(2) # Do something...
def __enter__(self):
try:
self.run()
except Exception as exc:
print('Error: {} exception raised by thread'.format(exc))
raise # reraise the exception
return self
def __exit__(self, *args):
self.cleanup()
print('main thread begins execution')
with MyThread('hello') as thread:
print('doing other things in main thread while other thread is running')
print('main thread continuing...')
輸出:
main thread begins execution
other thread now running...
doing other things in main thread while other thread is running
cleaning up after thread
main thread continuing on...
如果更改TEST_THREAD_EXCEPTION
到True
,cleanup()
不會被稱爲因爲線程沒有成功運行,但你可以改變,如果你願意,但可能還需要確保它不會被調用兩次。下面是該代碼在這種情況下,上述的作用:
main thread begins execution
Error: OOPS! exception raised by thread
Traceback (most recent call last):
File "opposite_init.py", line 37, in <module>
with MyThread('hello') as thread:
File "opposite_init.py", line 27, in __enter__
self.run()
File "opposite_init.py", line 21, in run
raise RuntimeError('OOPS!') # force exception
RuntimeError: OOPS!
爲什麼你不使用'try:... finally:...'構造? – Leon
雖然'__del __()'被認爲是相反的,但它在被調用時會有問題。我會看看上下文管理器,用在'with'子句中。 – AChampion