web-dev-qa-db-fra.com

Python Exception dans le thread Thread-1 (très probablement déclenchée lors de l'arrêt de l'interpréteur)?

Mon ami et moi avons travaillé sur un grand projet pour apprendre et pour s'amuser dans python et PyGame. Fondamentalement, c'est une simulation AI d'un petit village. Nous voulions un cycle jour/nuit donc je trouvé un moyen pratique de changer la couleur d'une surface entière en utilisant numpy (en particulier le tutoriel de fondu enchaîné) - 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 <1 fps lent. donc je regarde dans le threading (parce que je voulais l'ajouter éventuellement) et j'ai trouvé cette page sur les files d'attente - En savoir plus sur le module Queue dans python (comment l'exécuter)

Je passe environ 15 minutes à créer un système de base mais dès que je le lance, la fenêtre se ferme et il dit

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

EDIT: C'est littéralement tout ce qu'il dit, aucune erreur de trace

Je ne sais pas ce que je fais mal, mais je suppose que je 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 aider, ce serait grandement apprécié. Je vous remercie.

23
Nick Jarvis

Ceci est assez courant lors de l'utilisation de threads démon. Pourquoi définissez-vous .daemon = True Sur vos discussions? Pensez-y. Bien qu'il existe des utilisations légitimes pour les threads démon, la plupart 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 se bloquera quitter si je ne le fais pas, donc je sais! Je dirai que ce sont des threads de démon. Ensuite, l'interprète n'attendra pas qu'ils se terminent à la fin. Problème résolu. "

Mais ce n'est pas résolu - cela crée généralement d'autres problèmes. En particulier, les threads du démon continuent de s'exécuter pendant que l'interpréteur - à sa sortie - se détruit. 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 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 est si avancée que même le module sys ne contient plus rien utilisable. L'implémentation de threading conserve une référence à sys.stderr En interne afin qu'il puisse vous dire quelque chose alors (spécifiquement, le message exact que vous voyez), mais trop d'interprète a été détruit pour vous dire autre chose sur ce qui n'a pas fonctionné.

Trouvez donc un moyen de fermer proprement vos discussions (et supprimez .daemon = True). Je ne connais pas assez votre problème pour suggérer une manière spécifique, mais vous penserez à quelque chose ;-)

BTW, je suggère de supprimer les arguments maxsize=0 Sur vos constructeurs Queue(). La valeur par défaut est "illimité" et "tout le monde le sait", alors que peu de gens savent que maxsize=0 Signifie également "illimité". Cela a empiré 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 illimité" est toujours universellement vrai.

49
Tim Peters