是否有可能终止一个正在运行的线程而不设置/检查任何标志/信号/等等?
当前回答
下面的方法可以用来杀死一个线程:
kill_threads = False
def doSomething():
global kill_threads
while True:
if kill_threads:
thread.exit()
......
......
thread.start_new_thread(doSomething, ())
这甚至可以用于从主线程终止代码写在另一个模块中的线程。我们可以在该模块中声明一个全局变量,并使用它来终止在该模块中生成的线程。
我通常使用它在程序出口终止所有线程。这可能不是终止线程的完美方法,但可能有帮助。
其他回答
我想补充的一件事是,如果你阅读threading lib Python的官方文档,建议避免使用“恶魔”线程,当你不希望线程突然结束时,带有Paolo Rovelli提到的标志。
来自官方文件:
守护进程线程在关机时突然停止。它们的资源(如打开的文件、数据库事务等)可能无法正确释放。如果您希望线程优雅地停止,请将它们设置为非守护进程,并使用适当的信号机制(如Event)。
我认为创建守护线程取决于您的应用程序,但通常(在我看来)最好避免杀死它们或使它们成为守护线程。在多处理中,您可以使用is_alive()来检查进程状态,并使用“terminate”来完成它们(也可以避免GIL问题)。但有时,当你在Windows中执行代码时,你会发现更多的问题。
并且永远记住,如果你有“活动线程”,Python解释器将运行等待它们。(因为这个守护程序可以帮助你如果不重要的事情突然结束)。
正如@Kozyarchuk的回答中提到的,安装跟踪工作。由于这个答案不包含代码,下面是一个工作就绪的示例:
import sys, threading, time
class TraceThread(threading.Thread):
def __init__(self, *args, **keywords):
threading.Thread.__init__(self, *args, **keywords)
self.killed = False
def start(self):
self._run = self.run
self.run = self.settrace_and_run
threading.Thread.start(self)
def settrace_and_run(self):
sys.settrace(self.globaltrace)
self._run()
def globaltrace(self, frame, event, arg):
return self.localtrace if event == 'call' else None
def localtrace(self, frame, event, arg):
if self.killed and event == 'line':
raise SystemExit()
return self.localtrace
def f():
while True:
print('1')
time.sleep(2)
print('2')
time.sleep(2)
print('3')
time.sleep(2)
t = TraceThread(target=f)
t.start()
time.sleep(2.5)
t.killed = True
它在输出1和2之后停止。3不打印。
这是基于thread2—可杀死线程ActiveState配方。
您需要调用PyThreadState_SetAsyncExc(),它只能通过ctypes模块使用。
这只在Python 2.7.3上进行了测试,但它很可能与最近的其他2一起工作。x版本。PyThreadState_SetAsyncExc()仍然存在于Python 3中以实现向后兼容性(但我还没有测试它)。
import ctypes
def terminate_thread(thread):
"""Terminates a python thread from another thread.
:param thread: a threading.Thread instance
"""
if not thread.isAlive():
return
exc = ctypes.py_object(SystemExit)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
ctypes.c_long(thread.ident), exc)
if res == 0:
raise ValueError("nonexistent thread id")
elif res > 1:
# """if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"""
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
这似乎与windows 7上的pywin32一起工作
my_thread = threading.Thread()
my_thread.start()
my_thread._Thread__stop()
如果您显式地调用time.sleep()作为线程的一部分(比如轮询一些外部服务),对Phillipe方法的改进是在sleep()的任何地方使用事件的wait()方法中的超时。
例如:
import threading
class KillableThread(threading.Thread):
def __init__(self, sleep_interval=1):
super().__init__()
self._kill = threading.Event()
self._interval = sleep_interval
def run(self):
while True:
print("Do Something")
# If no kill signal is set, sleep for the interval,
# If kill signal comes in while sleeping, immediately
# wake up and handle
is_killed = self._kill.wait(self._interval)
if is_killed:
break
print("Killing Thread")
def kill(self):
self._kill.set()
然后运行它
t = KillableThread(sleep_interval=5)
t.start()
# Every 5 seconds it prints:
#: Do Something
t.kill()
#: Killing Thread
使用wait()而不是sleep()ing和定期检查事件的优点是,您可以在更长的睡眠间隔中编程,线程几乎立即停止(否则您将处于sleep()ing),并且在我看来,处理退出的代码明显更简单。
推荐文章
- 如何在Python中进行热编码?
- 如何嵌入HTML到IPython输出?
- 在Python生成器上使用“send”函数的目的是什么?
- 是否可以将已编译的.pyc文件反编译为.py文件?
- Django模型表单对象的自动创建日期
- 在Python中包装长行
- ExecutorService,如何等待所有任务完成
- 如何计算两个时间串之间的时间间隔
- 我如何才能找到一个Python函数的参数的数量?
- 您可以使用生成器函数来做什么?
- 将Python诗歌与Docker集成
- 提取和保存视频帧
- 使用请求包时出现SSL InsecurePlatform错误
- 如何检索Pandas数据帧中的列数?
- except:和except的区别: