AggregateException
例如,在发生KeyboardInterrupts时如何停止两个线程? 因为对于“ KeyboardInterrupt除外”,线程仍在运行:/
重要: 问题是仅使用模块_thread关闭线程! 有可能吗?
答案 0 :(得分:0)
除主线程外,无法直接与另一个线程进行交互。尽管某些平台确实提供了线程取消或杀死语义,但Python并没有公开它们,这是有充分理由的。 1
因此,通常的解决方案是使用某种信号告诉所有人退出。一种可能性是带有done
的{{1}}标志:
Lock
当然,如果您使用done = False
donelock = _thread.allocate_lock()
def test1():
while True:
try:
donelock.acquire()
if done:
return
finally:
donelock.release()
time.sleep(1)
print('TEST1')
_thread.start_new_thread(test1,())
time.sleep(3)
try:
donelock.acquire()
done = True
finally:
donelock.release()
(或Qt的线程之类的其他更高级别的API),同一件事会更清洁。另外,您可以使用threading
或Condition
使后台线程尽快退出,而不是仅在下一个Event
完成之后退出。
sleep
done = threading.Event()
def test1():
while True:
if done.wait(1):
return
print('TEST1')
t1 = threading.Thread(target=test1)
t1.start()
time.sleep(3)
done.set()
模块当然没有_thread
或Event
,但是您始终可以自己构建一个,也可以只构建borrowing from the threading
source。
或者,如果您希望异步杀死线程(显然,如果线程正在写文件,那是不安全的,但是如果它们只是在进行计算或下载等无关紧要的操作, (如果您要取消,那很好)),Condition
使其变得更加容易:
threading
请注意,您看到的行为实际上在跨平台上并不可靠:
t1 = threading.Thread(target=test1, daemon=True)
创建的背景线程可能会继续运行,或者半干净地关闭,或者硬终止。因此,当您在便携式应用程序中使用_thread
时,必须编写可处理这三个条件中的任何一个的代码。_thread
可以传递到任意线程而不是主线程。如果是这样,除非您已设置处理程序,否则它通常会杀死该线程。因此,如果您使用的是KeyboardInterrupt
,通常需要处理_thread
并调用KeyboardInterrupt
。此外,我不认为您的_thread.interrupt_main()
在做什么。 except:
仅涵盖try
个调用。如果线程成功启动,则主线程退出start_new_thread
块并到达程序结尾。如果引发try
或其他异常,则不会触发KeyboardInterrupt
。 (此外,如果您想了解代码在做什么,则使用裸露的except:
甚至不记录处理了哪个异常都是一个糟糕的主意。)大概在平台上,后台线程继续运行,和它们上的主线程块(可能是在OS级别,而不是Python级别,因此没有可以编写的代码参与其中)。
如果您希望主线程继续运行以确保它可以处理except:
等问题(但请注意上面的注意事项!),则必须给它提供代码以继续运行:>
KeyboardInterrupt
1。 Windows上的TerminateThread
使得无法进行Python需要做的所有清理工作。 pthread_cancel
可以在POSIX系统(例如Linux和macOS)上实现,但非常困难。两者之间的语义差异足够大,以致于试图编写跨平台的包装器将是一场噩梦。更不用说Python支持的系统(主要是较旧的Unix)没有完整的try:
while True:
time.sleep(1<<31)
except KeyboardInterrupt:
# background-thread-killing code goes here.
API,甚至没有完全不同的线程API。