Exception Python dans thread Thread-1 (probablement soulevée lors de l'arrêt de l'interpréteur)?

Mon ami et moi avons travaillé sur un grand projet pour apprendre et pour le plaisir en Python et PyGame. Fondamentalement, il est une simulation AI d'un petit village. nous voulions un cycle jour / nuit donc j'ai trouvé un moyen de changer la couleur d'une surface entière en utilisant numpy (en particulier le tutoriel cross-fade) - http://www.pygame.org/docs/tut/surfarray/SurfarrayIntro.html

Je l'ai implémenté dans le code et cela fonctionne, mais il est extrêmement lent, comme apprendre sur le module de file d'attente en python (comment l'exécuter)

Je passe environ 15 minutes à faire un système de base mais dès que je l'exécute, la fenêtre se ferme et il est dit

Exception in thread Thread-1 (most likely raised during interpreter shutdown):

EDIT: c'est littéralement tout ce qu'il dit, pas d'erreur de retraçage

Je ne sais pas ce que je fais mal, mais je suppose qu'il me manque quelque chose de simple. J'ai ajouté les parties nécessaires du code ci-dessous.

q_in = Queue.Queue(maxsize=0)

q_out = Queue.Queue(maxsize=0)

def run():    #Here is where the main stuff happens
    #There is more here I am just showing the essential parts
    while True:
        a = abs(abs(world.degree-180)-180)/400.

        #Process world
        world.process(time_passed_seconds)

        blank_surface = pygame.Surface(SCREEN_SIZE)
        world.render(blank_surface)    #The world class renders everything onto a blank surface
        q_in.put((blank_surface, a))
        screen.blit(q_out.get(), (0,0))

def DayNight():
    while True:
        blank_surface, a = q_in.get()
        imgarray = surfarray.array3d(blank_surface)  # Here is where the new numpy       stuff starts (AKA Day/Night cycle)
        src = N.array(imgarray)
        dest = N.zeros(imgarray.shape)
        dest[:] = 20, 30, 120
        diff = (dest - src) * a
        xfade = src + diff.astype(N.int)

        surfarray.blit_array(blank_surface, xfade)
        q_out.put(blank_surface)
        q_in.task_done()

def main():
    MainT = threading.Thread(target=run)
    MainT.daemon = True
    MainT.start()

    DN = threading.Thread(target=DayNight)
    DN.daemon = True
    DN.start()

    q_in.join()
    q_out.join()

Si quelqu'un pouvait de l'aide, il serait grandement apprécié. Merci.

21
demandé sur Community 2013-12-15 20:37:16

1 réponses

C'est assez courant lors de l'utilisation de threads démon. Pourquoi définissez-Vous .daemon = True sur vos threads? Pensez à ce sujet. Bien qu'il existe des utilisations légitimes pour les threads du démon, la plupart des fois qu'un programmeur le fait parce qu'ils sont confus, comme dans "Je ne sais pas comment fermer mes threads proprement, et le programme gèlera à la sortie si Je ne le fais pas, donc je sais! Je dirai que ce sont des fils de démon. Ensuite, l'interprète n'attendra pas qu'ils se terminent quand il sort. Le problème est résolu."

Mais il n'est pas résolu-cela crée généralement d'autres problèmes. En particulier, les threads du démon continuent à s'exécuter pendant que l'interpréteur se détruit lui - même. Les Modules sont détruits, stdin et stdout et stderr sont détruits, etc etc. Toutes sortes de choses peuvent alors mal tourner dans les threads du démon, car les choses auxquelles ils essaient d'Accéder sont annihilées.

Le message spécifique que vous voyez est produit lorsqu'une exception est déclenchée dans un thread, mais la destruction de l'interpréteur a été telle que même le module sys ne contient plus rien d'utilisable. L'implémentation de threading conserve une référence à sys.stderr en interne afin qu'elle puisse vous dire quelque chose ensuite (spécifiquement, le message exact que vous voyez), mais trop de l'interpréteur a été détruit pour vous dire quoi que ce soit d'autre sur ce qui a mal tourné.

Trouvez donc un moyen d'arrêter vos threads proprement à la place (et supprimez .daemon = True). Vous n'en savez pas assez sur votre problème pour suggérer une manière spécifique, mais vous penserez de quelque chose ;-)

BTW, je suggère de supprimer les arguments maxsize=0 sur vos constructeurs Queue(). La valeur par défaut est "unbounded", et "everyone knows that", tandis que peu de gens savent que maxsize=0 signifie aussi "unbounded". Cela s'est aggravé car d'autres types de données ont pris maxsize=0 pour signifier "la taille maximale est vraiment 0" (le meilleur exemple est collections.deque); mais "aucun argument ne signifie unbounded" est toujours universellement vrai.

45
répondu Tim Peters 2013-12-15 19:32:10