多线程Python应用在运行线程时挂起
我正在尝试创建一个名为 MainObject 的对象,它可以作为 DBus 服务使用。这个 MainObject 应该始终能够响应其他对象或进程,因此在处理它的项目时不能阻塞。为此,我将项目放在一个单独的线程中,一个接一个地处理(就像排队一样)。你可以通过 DBus 或命令行向 MainObject 添加项目。我简化了示例(没有 DBus,也没有命令行),只是为了展示我的问题。
我的问题是,如果我重新启用 'tt.join()',应用程序就会按预期工作,但这会阻塞其他进程。没办法,tt.join 会让应用程序等待,直到这个单独的线程完成它的工作。另一方面,如果 'tt.join()' 保持禁用,应用程序不会阻塞外部的 DBus 事件,但却永远不会显示 'ThreadTest done!'(看看实际输出)。
我想要的是,能够得到我期望的输出,同时应用程序也能保持响应。
#!/usr/bin/python2.5
import gobject
import threading
import re
import time
class ThreadTest(threading.Thread):
def __init__(self):
threading.Thread.__init__ (self)
print ' ThreadTest created!'
def run(self):
print ' ThreadTest running ...'
time.sleep(1)
print ' ThreadTest done!'
return True
class MainObject():
def __init__(self):
self.timer = gobject.timeout_add(1000, self.update)
self.loop = gobject.MainLoop()
print 'MainObject created!'
def update(self):
print 'MainObject updating ...'
if self.check_running() == False:
tt = ThreadTest()
tt.start()
#tt.join()
return True
def check_running(self):
running = False
expr = re.compile('ThreadTest')
for threadstr in threading.enumerate():
matches = expr.findall(str(threadstr))
if matches:
running = True
return running
mo = MainObject()
mo.loop.run()
期望的输出:
MainObject created!
MainObject updating ...
ThreadTest created!
ThreadTest running ...
ThreadTest done!
MainObject updating ...
ThreadTest created!
ThreadTest running ...
ThreadTest done!
MainObject updating ...
ThreadTest created!
ThreadTest running ...
ThreadTest done!
MainObject updating ...
ThreadTest created!
ThreadTest running ...
ThreadTest done!
MainObject updating ...
ThreadTest created!
ThreadTest running ...
ThreadTest done!
实际输出:
MainObject created!
MainObject updating ...
ThreadTest created!
ThreadTest running ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
MainObject updating ...
2 个回答
在Python中,线程可能会让人感到困惑——这其实是一个未解决的问题。主要的问题在于GIL,也就是Python的全局解释器锁。
为了克服这个问题,Python引入了一个叫“multiprocessing”的模块(在Python 2.6中新增)——它保留了“threading”的接口,但实际上是在一个单独的进程中运行代码。你可以尝试把线程替换成多进程——但是:所有的数据库交互、图形界面等操作都要在主“线程”(也就是一个单独的进程)中进行,然后和子进程交换数据(比如字符串、列表、字典等)……这样是可以正常工作的。
另外,我搞不懂为什么要用这么复杂的正则表达式来检查某个字符串是否在`threading.enumerate`的返回值中?Python其实有“in”这个操作符(所以你根本不需要使用字符串的索引或查找方法):
你可以用以下代码替换掉整个check_running
方法:
def check_running(self):
return 'ThreadTest' in str(threading.enumerate())
默认情况下,gobject 的绑定并不支持多线程。请在导入 gobject
之后,尝试执行以下操作:
gobject.threads_init()