使用Tkinter扫描线程违规
我们快要完成一个很大的应用更新,这个应用是用python2.5和Tkinter开发的,但不幸的是,出现了以下错误:
alloc: invalid block: 06807CE7: 1 0 0
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
我们以前见过这个错误,通常是因为一个非图形界面的线程试图通过Tkinter访问TK,导致了Tcl解释器错误(因为TK不是线程安全的)。这个错误在应用关闭时出现,发生在python解释器处理完我们的代码之后。这个错误很难重现,我在想我可能需要检查系统中的所有线程,看看它们是否在不该访问TK的时候访问了它。
我在寻找一个神奇的python技巧来帮助解决这个问题。我们使用的所有Tkinter组件都是先进行子类化,并继承自我们自己的Widget基类。
考虑到这一点,我想在每个组件子类的方法开始处添加一个检查:
import thread
if thread.get_ident() != TKINTER_GUI_THREAD_ID:
assert 0, "Invalid thread accessing Tkinter!"
我想到装饰器可以部分解决这个问题。不过,我不想手动给每个方法添加装饰器。有没有办法可以把装饰器添加到所有继承自我们Widget基类的类的方法上?或者有没有更好的方法来处理这个问题?或者有没有人对这个错误有更多的信息?
enter code here
2 个回答
1
我不太清楚你的方法是否好,因为我对Tkinter不太了解。
不过,这里有一个示例,展示了如何使用元类来装饰所有类的方法。
import functools
# This is the decorator
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print 'calling', func.__name__, 'from decorator'
return func(*args, **kwargs)
return wrapper
# This is the metaclass
class DecorateMeta(type):
def __new__(cls, name, bases, attrs):
for key in attrs:
# Skip special methods, e.g. __init__
if not key.startswith('__') and callable(attrs[key]):
attrs[key] = my_decorator(attrs[key])
return super(DecorateMeta, cls).__new__(cls, name, bases, attrs)
# This is a sample class that uses the metaclass
class MyClass(object):
__metaclass__ = DecorateMeta
def __init__(self):
print 'in __init__()'
def test(self):
print 'in test()'
obj = MyClass()
obj.test()
元类会改变类的创建过程。它会遍历正在创建的类的所有属性,并用my_decorator
来装饰所有可以调用的、名字比较“普通”的属性。
0
我选择了一种稍微简单一点的方法。我使用了 __getattribute__
这个方法。代码如下:
def __getattribute__(self, name):
import ApplicationInfo
import thread, traceback
if ApplicationInfo.main_loop_thread_id != thread.get_ident():
print "Thread GUI violation"
traceback.print_stack()
return object.__getattribute__(self, name)
果然,我们发现了一个比较隐蔽的地方,在这个地方我们在TK中访问状态时,并没有在主界面线程里。
虽然我得承认,我需要再复习一下我的Python,看到你的例子让我感觉像个新手。