Сканирование на предмет наличия нарушений с помощью Tkinter

1

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

Мы видели это раньше, и обычно это ошибка Tcl Interrupter, вызванная тем, что поток non GUI пытается получить доступ к TK через Tkinter в любом случае (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
Теги:
multithreading
tkinter

2 ответа

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

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

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.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню