2010-07-15 7 views
2

en utilisant le code de ce site: http://www.saltycrane.com/blog/2008/09/simplistic-python-thread-example/Comment faire du threading en python?

Le code est

import time 
from threading import Thread 

def myfunc(i): 
    print "sleeping 5 sec from thread %d" % i 
    time.sleep(5) 
    print "finished sleeping from thread %d" % i 

for i in range(10): 
    t = Thread(target=myfunc, args=(i,)) 
    t.start() 

et je reçois cette sortie:

sleeping 5 sec from thread 0 
sleeping 5 sec from thread 1 
sleeping 5 sec from thread 2 
sleeping 5 sec from thread 3 
sleeping 5 sec from thread 4 
sleeping 5 sec from thread 5 
sleeping 5 sec from thread 6 
sleeping 5 sec from thread 7 
sleeping 5 sec from thread 8 
sleeping 5 sec from thread 9 
finished sleeping from thread 0 
finished sleeping from thread 2 
finished sleeping from thread 4 
finished sleeping from thread 1finished sleeping from thread 6finished sleeping from thread 8 
finished sleeping from thread 5finished sleeping from thread 7finished sleeping from thread 9 

finished sleeping from thread 3 

ce qui se passe ici? Je suis d'accord avec les threads ne pas imprimer dans l'ordre parce que c'est possible, mais pourquoi ne sont-ils pas d'impression sur les nouvelles lignes à la fin? J'utilise python 2.6 sous windows xp

Répondre

2

Je pense que quand un thread n'a pas imprimé une nouvelle ligne, c'est parce que le contrôle a été passé à un autre thread avant que le premier thread n'imprime la nouvelle ligne.

+0

Je pense que vous avez peut-être raison. Cela doit signifier que la commande d'impression envoie seulement un caractère à la fois. Il y a 10 caractères de nouvelle ligne parce que j'ai vérifié ... Étrange que seulement les caractères de nouvelle ligne ont été décalés. doit juste être le moment. – Richard

+3

Il n'imprime pas un caractère à la fois (bien sûr, à un certain niveau, il l'est); c'est juste que le comportement de l'instruction print est composé de deux étapes: 'print the argument' suivi de 'print newline si l'argument n'a pas été suivi d'une virgule'. Le planificateur de threads Python peut basculer les threads entre ces deux étapes, mais il ne bascule pas au milieu d'un, d'où le comportement que vous voyez. –

0

Parce que l'impression n'est pas atomic l'impression d'un thread peut être interrompue par un autre thread à tout moment. Si thread1 est à moitié impression et thread2 l'interrompt et commence à imprimer, la sortie sera entrelacée avec la sortie de thread1 et thread2.

6

Vous venez de découvrir pourquoi la programmation avec des fils est difficile :)

Ce qui se passe est que tous vos fils sont se réveiller à peu près en même temps. Un fil commence à imprimer "fini de dormir à partir du fil 1" et avant qu'il ait une chance d'imprimer ce dernier "\ n", un autre fil vient et imprime "fini de dormir à partir du fil 6", et ainsi de suite. Ces nouvelles lignes ne sont pas ignorées, elles sont simplement déplacées et regroupées ailleurs. C'est probablement pourquoi une ligne a été sauté avant "fini ... 3". Ma conjecture est qu'il ya beaucoup de lignes vierges qui ont été supprimées en raison de la mise en forme.

Utilisez threading.Lock pour mettre la synchronisation autour de vos instructions print afin que plusieurs print ne puissent pas se produire en même temps.

0

En effet, il n'est pas sécuritaire d'imprimer. Dans votre exemple, vous pouvez utiliser le module de journalisation. Ou vous pouvez créer un thread safe print.

5

impression implémentée par plusieurs opcodes, en particulier la nouvelle ligne est une séparée. Python va changer de contexte entre les opcodes:

>>> def f(o): 
...  print o 
...  
...  

>>> from dis import dis 

>>> dis(f) 
    2   0 LOAD_FAST    0 (o) 
       3 PRINT_ITEM   
       4 PRINT_NEWLINE  
       5 LOAD_CONST    0 (None) 
       8 RETURN_VALUE