退出 python 线程的更多 pythonic 方法 - 守护程序与 stop_event
More pythonic way to exit a python thread - daemon vs stop_event
以下代码:
import threading
import time
from functools import partial
from itertools import count
def daemon_loop(sleep_interval, stop_event):
for j in count():
print(j)
if stop_event.is_set():
break
time.sleep(sleep_interval)
print('Slept %s' % sleep_interval)
print('Prod terminating')
if __name__ == '__main__':
stop_event = threading.Event() #
target = partial(daemon_loop, sleep_interval=2, stop_event=stop_event)
prod_thread = threading.Thread(target=target,
# daemon=True
)
try:
prod_thread.start()
while True:
time.sleep(10)
except KeyboardInterrupt:
print('Terminating...')
stop_event.set()
在键盘中断时打印:
C:\Users\MrD\.PyCharm2018.2\config\scratches>c:\_\Python363-64\python.exe thread_daemon.py
0
Slept 2
1
Terminating...
Slept 2
2
Prod terminating
取消注释 # daemon=True
行会导致 prod_thread 立即结束:
C:\Users\MrD\.PyCharm2018.2\config\scratches>c:\_\Python363-64\python.exe thread_daemon.py
0
Slept 2
1
Terminating...
我的问题是 preferred/more pythonic 处理线程终止的方法是什么——我应该放弃事件机制并只将线程标记为守护进程还是我错过了一些边缘情况?
参见:
- Daemon Threads Explanation
我做得还不够 Python 无法给你 "Pythonic" 答案,但我可以用更通用的编程术语来回答。
首先,我不喜欢终止线程。有 是 安全和正常的情况,比如你在这里的例子 - 但是在 print
中间终止写入它的输出会感觉有点脏。
其次,如果您想继续使用 sleep
(我也不喜欢),您可以在 if stop_event.is_set():
和 break
之后重复该睡觉了。 (不要移动代码,复制它。)在这种情况下 sleep
的主要问题是它会等待完整的 sleep_interval
,即使在那段时间内设置了事件。
第三 - 我的偏好 - 而不是使用 sleep
,对事件执行 wait
超时。如果等待期间没有设置事件,等待超时时间后wait
returnsfalse。如果事件 在等待 之前或期间设置, wait
returns true 立即 (即中止超时,让您快速、干净地关闭线程。)
因此您的代码将如下所示:
def daemon_loop(sleep_interval, stop_event):
for j in count():
print(j)
if stop_event.wait(sleep_interval):
break
print('Slept %s' % sleep_interval)
print('Prod terminating')
以下代码:
import threading
import time
from functools import partial
from itertools import count
def daemon_loop(sleep_interval, stop_event):
for j in count():
print(j)
if stop_event.is_set():
break
time.sleep(sleep_interval)
print('Slept %s' % sleep_interval)
print('Prod terminating')
if __name__ == '__main__':
stop_event = threading.Event() #
target = partial(daemon_loop, sleep_interval=2, stop_event=stop_event)
prod_thread = threading.Thread(target=target,
# daemon=True
)
try:
prod_thread.start()
while True:
time.sleep(10)
except KeyboardInterrupt:
print('Terminating...')
stop_event.set()
在键盘中断时打印:
C:\Users\MrD\.PyCharm2018.2\config\scratches>c:\_\Python363-64\python.exe thread_daemon.py
0
Slept 2
1
Terminating...
Slept 2
2
Prod terminating
取消注释 # daemon=True
行会导致 prod_thread 立即结束:
C:\Users\MrD\.PyCharm2018.2\config\scratches>c:\_\Python363-64\python.exe thread_daemon.py
0
Slept 2
1
Terminating...
我的问题是 preferred/more pythonic 处理线程终止的方法是什么——我应该放弃事件机制并只将线程标记为守护进程还是我错过了一些边缘情况?
参见:
- Daemon Threads Explanation
我做得还不够 Python 无法给你 "Pythonic" 答案,但我可以用更通用的编程术语来回答。
首先,我不喜欢终止线程。有 是 安全和正常的情况,比如你在这里的例子 - 但是在 print
中间终止写入它的输出会感觉有点脏。
其次,如果您想继续使用 sleep
(我也不喜欢),您可以在 if stop_event.is_set():
和 break
之后重复该睡觉了。 (不要移动代码,复制它。)在这种情况下 sleep
的主要问题是它会等待完整的 sleep_interval
,即使在那段时间内设置了事件。
第三 - 我的偏好 - 而不是使用 sleep
,对事件执行 wait
超时。如果等待期间没有设置事件,等待超时时间后wait
returnsfalse。如果事件 在等待 之前或期间设置, wait
returns true 立即 (即中止超时,让您快速、干净地关闭线程。)
因此您的代码将如下所示:
def daemon_loop(sleep_interval, stop_event):
for j in count():
print(j)
if stop_event.wait(sleep_interval):
break
print('Slept %s' % sleep_interval)
print('Prod terminating')