[英]Python Threading - Managing thread termination and the main thread
Before you read on, know that I'm new to Python and very new to threading so forgive me if I misunderstand how threads work or make a rookie error :P 在你继续阅读之前,要知道我是Python新手并且对线程很新,所以请原谅我,如果我误解了线程的工作方式或新手错误:P
Short description of my goal: 我的目标的简短描述:
Here's what I have so far (the basics): 这是我到目前为止(基础知识):
import threading, time
def printCount():
print "Thread B started"
x = 0
while True:
time.sleep(1)
x = x + 1
print x
## User Code ##
print "begin!"
threadB = threading.Thread(target=printCount)
threadB.start()
print "woop!"
The requirements are: 要求是:
except
KeyboardInterrupt: os._exit(1))
在任何时候按Ctrl + C都应该终止整个程序而不运行任何线程(使用类似: except
KeyboardInterrupt: os._exit(1))
except
KeyboardInterrupt: os._exit(1))
except
KeyboardInterrupt: os._exit(1))
inside User Code is fine except
KeyboardInterrupt: os._exit(1))
用户代码里面很好 This example is not my actual goal, just a simplified version of the problem I'm having. 这个例子不是我的实际目标,只是我遇到的问题的简化版本。 I'm trying to make an IRC framework where the user can import it and use the API very simply without messying their own code with threads and interrupts and the like. 我正在尝试创建一个IRC框架,用户可以在其中导入它并非常简单地使用API,而不会使用线程和中断等来清除自己的代码。 This is why it's important for the user code to be as clean as possible. 这就是为什么用户代码尽可能干净是很重要的。
The framework would allow the user to create an IRC bot which runs forever, listening to commands whilst allowing the user to add their own commands. 该框架将允许用户创建一个永远运行的IRC机器人,在允许用户添加自己的命令的同时监听命令。 The Github link is here if you're interested (It's very WIP atm). 如果您感兴趣的话,Github链接就在这里 (这是非常重要的WIP)。
Wrote a short note on another question yesterday having similar issues, this is a check you could implement in the subthread "b": 在昨天的另一个问题上写了一个关于类似问题的简短说明,这是你可以在子线程“b”中实现的检查:
Instead of while 1:
do the following: 而不是while 1:
执行以下操作:
def printCount():
main = None
for t in threading.enumerate():
if t.name == 'MainThread':
main = t
print "Thread B started"
x = 0
while main and main.isAlive():
time.sleep(1)
x = x + 1
print x
It would be a good idea to store main
in the global scope for all threads to use isntead of having to look up the main thread each and every initation of the sub-thread. 将main
存储在全局范围内以供所有线程使用是一个好主意,而不必在每个子线程的初始化时查找主线程。 But this would do the work in your example. 但这可以在你的例子中完成工作。
main
will be the handle towards your main thread by iterating through all threads ( .enumerate()
) and then placing the thread called "MainThread" into main
and then calling main.isAlive()
to check if it's still running. main
将通过迭代所有线程( .enumerate()
)然后将名为“MainThread”的线程放入main
,然后调用main.isAlive()
来检查它是否仍在运行,从而处理主线程。 if main
is None
or False
or if .isAlive()
returns False
it will indicate that the thread is either non-existant or dead, shutting down your subthread :) 如果main
为None
或False
或者.isAlive()
返回False
,则表示该线程不存在或死亡,关闭子线程:)
You cannot "switch" threads. 你不能“切换”线程。 So once you're done with your main thread, you have to wait for the other threads to terminate using the method join
. 因此,一旦完成主线程,就必须等待其他线程使用方法join
终止。 But note this: 但请注意:
join
method is not interruptible with KeyboardInterrupt
, you need to specify a timeout and loop over to detect user interrupts. 由于join
方法是不是可中断的KeyboardInterrupt
,您需要通过指定超时和循环检测用户中断。 sys.stdout
(used when you print) 您还需要使用threading.Lock来阻止对共享资源的并发访问,例如sys.stdout
(打印时使用) I gathered these aspects in a class called ThreadHandler
, please have a look: 我在一个名为ThreadHandler
的类中收集了这些方面,请看一下:
import threading, time
def printCount(lock, stop):
with lock:
print "Thread B started"
x = 0
while not stop.is_set():
time.sleep(1)
x = x + 1
with lock:
print x
class ThreadHandler():
STEP = 0.2
def __init__(self, target):
self.lock = threading.Lock()
self.stop = threading.Event()
args = (self.lock, self.stop)
self.thread = threading.Thread(target=target, args=args)
def start(self):
self.thread.start()
def join(self):
while self.thread.is_alive():
try:
self.thread.join(self.STEP)
except KeyboardInterrupt:
self.stop.set()
## User Code ##
print "begin!"
handler = ThreadHandler(target=printCount)
handler.start()
with handler.lock:
print "woop!"
handler.join()
You can't switch threads like that. 你无法像这样切换线程。 It doesn't work like that. 它不像那样工作。
However you could use signals with a global flag ALIVE
: 但是,您可以使用带有全局标志ALIVE
信号:
import threading, time, signal
ALIVE = True
def handle_sigint(signum, frame):
global ALIVE
ALIVE = False
signal.signal(signal.SIGINT, handle_sigint)
def printCount():
print "Thread B started"
x = 0
while ALIVE: # <--- note the change
time.sleep(1)
x = x + 1
print x
## User Code ##
print "begin!"
threadB = threading.Thread(target=printCount)
threadB.start()
print "woop!"
signal.pause() # <--- wait for signals
Now it will gracefully quit after pressing CTRL+C. 现在按CTRL + C后它会正常退出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.