Python类中的简单线程管理
我正在尝试为Python写一个模块,这个模块可以在我的程序中打印文本,并在后台执行某些操作时显示进度条。目前我在使用“threading”模块,但如果有其他更简单的方法,我也愿意尝试。
我想知道的有两个方面,我应该如何优雅地调用这个类,以及我应该如何停止我创建的线程?
这是我目前的做法:
tmp1 = textprint("hello this is text")
tmp1.start()
# do something
tmp1.stop()
这些是我考虑过的选项,并且已经查看过:
使用 thread.name 来找到线程的名字,或者让线程返回一个名字以便之后停止它。或者传递一个数字来进行类似的线程识别。(这有点麻烦,并不是我最喜欢的解决方案。)
发送一个线程事件?- 从文档中我看到可以发送事件,也许可以用它来停止线程?
或者使用with语句,但我不太清楚在这个上下文中如何使用,而且我觉得大部分Python文档都非常混乱,根本不是为我写的。
我想要做的事情是这样的:
echo('hello')
(打印进度条等)- 然后当我想停止它时,使用echo.stop()
不过明显的问题是,stop函数不知道它要停止哪个线程。
这是我尝试做的一个框架:
import time
import string
import threading
class print_text(threading.Thread):
def __init__(self,arg=None):
super(print_text,self).__init__()
self._stop = False
self.arg=arg
def run (self):
# start thread for text
print self.txt
while not self._stop:
print "rude words"
def echo (self,txt):
self.txt=txt
self.start()
def stop(self):
self._stop = True
def stopped(self):
return self._stop == True
def __enter__(self):
print "woo"
return thing
def __exit__(self, type, value, traceback):
return isinstance(value, TypeError)
if __name__ == '__main__':
print_text.start.echo('this is text') # dunt werk
with print_text.echo('this is text'):
time.sleep(3)
print "done"
然后像这样调用它:
echo('this is text')
我还猜为了做到这一点,我需要
import echo from print_text
使用WITH的方式建议在里面放一个__enter__
和__exit__
的部分。我试过这些,但它们没有奏效,而且我也不知道自己在做什么,真的很感谢任何帮助,谢谢。
3 个回答
线程的名字很有用,特别是当你可能同时有多个子线程在运行同样的任务时,这样你就可以确保所有的子线程都能被停止。给线程起名字听起来是个不错的主意,而且也不会太麻烦,不过每个人的看法可能不同 :-)。下面是一些内容:
- 启动一个子线程来打印消息并显示一个进度条。
- 使用启动时给定的名字来停止这个子线程。
这样代码就简单多了。这样做能达到你的目的吗?
import time, threading
class print_text:
def __init__(self):
pass
def progress(self):
while not self._stop: # Update progress bar
print(".", sep="", end="")
time.sleep(.5)
def echo(self, arg="Default"): # Print message and start progress bar
print(arg)
self._stop = False
threading.Thread(target=self.progress, name="_prog_").start()
def stop(self):
self._stop = True
for t in threading.enumerate():
if t.name == "_prog_":
t.join()
tmp1 = print_text()
tmp1.echo("hello this is text")
time.sleep(10)
tmp1.stop()
print("Done")
在Python中,停止一个线程的最好方法是礼貌地请求它停止。传递新数据给线程的最佳方式是使用Queue
模块。
这两者在这篇文章中的代码中都有用到,代码展示了如何通过Python线程进行套接字通信,但与您的问题同样相关。如果你仔细阅读代码,你会注意到:
- 使用了
threading.Event()
,这个事件是通过外部的方法调用来设置的,线程会定期检查这个事件,以知道是否被请求停止。 - 使用
Queue.Queue()
来传递命令给线程,并接收它的响应。
你离写出能运行的代码已经很近了。只需要做一些小调整:
- print_text 是一个类。你需要用
print_text()
来创建它的实例。 - start 方法会返回一个 print_text 的实例,你需要把这个实例保存下来,这样才能调用 stop 和 echo:
t = print_text()
- enter 方法需要返回 self,而不是 thing。
- exit 方法应该设置 _stop 或者调用 stop()。
- echo 方法应该返回 self,这样才能和 with 语句一起使用。
下面是包含这些小修改的可运行代码:
import time
import string
import threading
class print_text(threading.Thread):
def __init__(self, arg=None):
super(print_text,self).__init__()
self._stop = False
self.arg=arg
def run (self):
# start thread for text
print self.txt
while not self._stop:
print "rude words"
def echo (self, txt):
self.txt=txt
self.start()
return self
def stop(self):
self._stop = True
def stopped(self):
return self._stop == True
def __enter__(self):
print "woo"
return self
def __exit__(self, type, value, traceback):
self._stop = True
return isinstance(value, TypeError)
if __name__ == '__main__':
t = print_text()
t.echo('this is text')
time.sleep(3)
t.stop()
with print_text().echo('this is text'):
time.sleep(3)
print "done"