Сканирование на предмет наличия нарушений с помощью Tkinter - PullRequest
1 голос
/ 03 марта 2011

Мы только что закончили очень большое обновление нашего приложения, созданного с помощью 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.

Мы видели это раньше иобычно это ошибка прерывателя Tcl, вызванная тем, что поток без графического интерфейса в любом случае пытается получить доступ к TK через Tkinter (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 голос
/ 03 марта 2011

Я не знаю, хорош ли ваш подход, так как я не знаю Ткинтера.

Но вот пример того, как декорировать все методы класса, используя метакласс.

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 голосов
/ 03 марта 2011

Я пошел немного более легким методом.Я использовал __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, не находясь в основном потоке графического интерфейса.

Хотя я должен признать,Мне нужно пересмотреть мой питон, чувствуя себя нубистно, глядя на твой пример.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...