2009-12-23 7 views
2

je reçois l'erreur suivante lors de l'utilisation multitraitement:erreur étrange dépicklage lors de l'utilisation multitraitement

Exception in thread Thread-2: 
Traceback (most recent call last): 
    File "/usr/lib/python2.6/threading.py", line 525, in __bootstrap_inner 
    self.run() 
    File "/usr/lib/python2.6/threading.py", line 477, in run 
    self.__target(*self.__args, **self.__kwargs) 
    File "/usr/lib/python2.6/multiprocessing/pool.py", line 282, in _handle_results 
    task = get() 
UnpicklingError: NEWOBJ class argument has NULL tp_new 

Je ne sais absolument pas ce que cela signifie, bien que cela ressemble à quelque chose qui ne va pas au niveau C. Quelqu'un peut-il nous éclairer là-dessus?

MISE À JOUR: Ok, donc j'ai trouvé comment résoudre ce problème. Mais je suis encore un peu perplexe. Je renvoie une instance de cette classe:

class SpecData(object): 
    def __init__(self, **kwargs): 
     self.__dict__.update(**kwargs) 
    def to_dict(self): 
     return self.__dict__ 

Si je renvoie une instance de cet objet, j'obtiens l'erreur. Cependant, si je l'appelle to_dict et retourne un dictionnaire, cela fonctionne. Qu'est-ce que je fais mal?

Répondre

3

Essayez d'utiliser le module pickle plutôt que le module cPickle - pickle est écrit en Python pur, et souvent il donne des messages d'erreur plus utiles que cPickle. (Bien que parfois j'ai dû faire une copie locale de pickle.py, et ajouter quelques instructions de débogage printf près de l'emplacement de l'erreur pour comprendre le problème.)

Une fois que vous dépistez le problème, vous peut revenir à cpickle.

(Je ne suis pas très familier avec le module multitraitement, donc je ne suis pas sûr si vous faites le décapage ou si c'est le cas, alors la façon la plus simple d'utiliser pickle plutôt que cpickle peut être de faire quelques correctifs de singe avant d'importer le module de multiprocessing/threading: import sys, pickle; sys.modules['cPickle']=pickle)

0

Je l'ai fait en fil de sécurité C++, Java et Delphi, mais pas Python, prenez donc mes commentaires avec un grain de sel.

This page on Python and Thread-Safety mentionne spécifiquement l'attribution d'un dictionnaire à être atomique et thread-safe. Peut-être que votre référence à votre classe personnalisée n'est pas sûre pour les threads? Essayez d'ajouter certains des mécanismes de verrouillage recommandés si vous préférez passer une classe de conteneur personnalisée entre deux threads.

Je trouve fascinant que l'état d'autres résultats de recherche avec force que Python est complètement thread-safe. The Python docs themself indique que les verrous et d'autres mécanismes sont fournis pour aider avec les applications threadées, il semble donc que c'est le cas des internets qui sont faux (cela arrive-t-il?).

Another StackOverflow question on python and thread-safety.

+0

Je n'utilise pas vraiment de threads. Le module multi-traitement fonctionne en démarrant des processus séparés. Ensuite, les processus communiquent en sérialisant les objets et en les passant dans une file d'attente. Je reçois une erreur lorsque cet objet est désérialisé. –

+1

@Kieveli, en ce qui concerne Python étant "complètement thread-safe", le point est que l'accès aux primitives et autres opérations internes qui sont effectuées par la machine virtuelle sont sûrs. Des choses comme des dictionnaires ne peuvent pas entrer dans des états non valides, planter la machine, etc., à cause d'un accès multithread. C'est assez différent de dire que votre application est immunisée contre les problèmes de synchronisation de threads. Les conditions de course et les impasses sont toujours possibles dans les applications mal conçues et doivent être traitées de la manière habituelle. Certaines installations (par exemple le module File d'attente) aident beaucoup, même au niveau de l'application. –

2

Je pense que c'est un problème de sélection/d'impossibilité de picotage de certaines fonctions python. Voir ce post:

http://khinsen.wordpress.com/2012/02/06/teaching-parallel-computing-in-python/

J'ai eu des problèmes similaires en utilisant django-céleri (qui utilise le module multiprocessing). Si mon code tâche thows erreurs qui ne sont pas eux-mêmes pickelable, cette exception multiprocessus/cornichon obscurcit les informations. Parce que je n'ai pas trouvé une meilleure façon de propager les erreurs, j'ai recours à la journalisation de débogage dans mon code de tâche pour le traquer. Je devrais probablement devenir plus intelligent sur ce que je passe sur la file d'attente (attention de ne pas mettre d'exceptions dans la file d'attente des messages, donc le module multi-processus n'essaie pas de les décoder/décoder).

Dans votre cas ci-dessus, vous devrez peut-être vous assurer que SpecData.__dict__ est sélectionnable.Voir http://docs.python.org/library/pickle.html#pickle-protocol