2011-03-03 2 views
1

Nous sommes sur le point de terminer une mise à jour très importante à notre application qui est construite avec python2.5 et Tkinter et l'erreur suivante est glissée dans tristement:Recherche de violations de fil avec 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. 

Nous avons vu cela avant et c'est généralement une erreur Tcl Interrupter causée quand un thread non GUI tente d'accéder à TK via Tkinter de toute façon (TK n'étant pas thread-safe). L'erreur apparaît à la fermeture de l'application, une fois que l'interruption Python est terminée avec notre code. Cette erreur est très difficile à reproduire et je pense que je vais devoir scanner tous les threads du système pour voir s'ils accèdent à TK quand ils ne le devraient pas. Je suis à la recherche d'un tour de magie en python pour vous aider à résoudre ce problème. Tous les widgets Tkinter que nous utilisons sont d'abord sous-classés et héritent de la propre classe de base Widget.

Dans cet esprit, je suis à la recherche d'un moyen d'ajouter le contrôle suivant au début de chaque méthode dans les sous-classes widget:

import thread 
if thread.get_ident() != TKINTER_GUI_THREAD_ID: 
    assert 0, "Invalid thread accessing Tkinter!" 

Décorateurs comme une solution partielle vient à l'esprit. Cependant, je ne veux pas ajouter manuellement des décorateurs à chaque méthode. Y at-il un moyen que je puisse ajouter le décorateur à toutes les méthodes d'une classe qui hérite de notre classe de base Widget? Ou y a-t-il une meilleure façon de faire tout cela? Ou est-ce que quelqu'un a plus d'informations sur cette erreur?

enter code here 

Répondre

0

Je suis allé avec une méthode légèrement plus facile. J'ai utilisé la méthode __getattribute__. Le code est le suivant:

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) 

et bien sûr nous avons trouvé un endroit obscur où nous accédons état de l'intérieur des savoirs traditionnels sans être dans le fil de l'interface principale.

Bien que je doive admettre que j'ai besoin de revoir mon python, se sentir noobish regardant votre exemple.

1

Je ne sais pas si votre approche est bonne, car je ne connais pas Tkinter.

Mais voici un exemple de la façon de décorer toutes les méthodes de classe à l'aide d'une métaclasse.

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() 

La métaclasse remplace la création de classe. Il boucle à travers tous les attributs de la classe en cours de création et décore tous les attributs appelables qui ont un nom "normal" avec my_decorator.

Questions connexes