2012-12-05 11 views
5

Ho riscontrato un problema durante l'utilizzo di pydev per i test in cui i miei test continuano a rimanere sospesi. Ho approfondito il problema e so qual è la causa principale. Ho fornito esempi del codice qui sotto che può essere utilizzato per riprodurre il problema.Problema Pydev PyUnit quando si utilizza thread.join per assicurarsi che tutti i thread siano uniti

Principalmente sto testando su Centos 6.3, python 2.7, eclipse juno, pydev 2.7.1, tuttavia il problema si verifica anche su Windows 7 con impostazioni simili.

Ho uno script python che funziona come un launcher di processi per server diversi thread (tutti all'interno di librerie di terze parti, quindi non posso rassegnare quel lato del sistema).

Per garantire che tutti i thread siano terminati alla fine del mio process.py ho una sezione di codice che tenta di unire tutti i thread prima di uscire.

for t in threading.enumerate():    
    if t.getName() != 'MainThread': 
     t.join() 

Questo funziona correttamente nel normale codice di produzione.

Il problema si verifica quando si eseguono test in PyUnit in eclipse con pydev. Ulteriori thread sono stati aggiunti a python che hanno causato il blocco dei miei test.

Se lancio il mio programma utilizzando Esegui come -> Python Run, il mio codice viene eseguito come previsto ed esce correttamente. Se lancio il mio programma usando Run As -> Python unit-test, il test si blocca sempre.

Se guardo a quali thread sono disponibili, il problema diventa chiaro. Utilizzando l'esempio di codice di test disponibile, posso vedere quando solo esegue il test come una corsa pitone, i seguenti fili sono mostrati (come previsto)

Thread: <bound method _MainThread.getName of <_MainThread(MainThread, started 140268135126784)>> 
Thread: <bound method ThreadClass.getName of <ThreadClass(Thread A, started 140268006471424)>> 
Thread: <bound method ThreadClass.getName of <ThreadClass(Thread B, started 140267927631616)>> 

durante l'esecuzione del test come unità test

Thread: <bound method _MainThread.getName of <_MainThread(MainThread, started 139904571213568)>> 
Thread: <bound method WriterThread.getName of <WriterThread(pydevd.Writer, started daemon 139904379361024)>> 
Thread: <bound method ThreadClass.getName of <ThreadClass(Thread A, started 139904130479872)>> 
Thread: <bound method ThreadClass.getName of <ThreadClass(Thread B, started 139904119990016)>> 
Thread: <bound method PyDBCommandThread.getName of <PyDBCommandThread(pydevd.CommandThread, started daemon 139904358381312)>> 
Thread: <bound method ReaderThread.getName of <ReaderThread(pydevd.Reader, started daemon 139904368871168)>> 
Thread: <bound method ServerComm.getName of <ServerComm(Thread-4, started 139904345736960)>> 

I thread aggiuntivi aggiunti da python sembrano interrompere questo codice. Quando il mio codice tenta di unirsi a ServerComm o pydev.Writer, si blocca.

So che potrei tentare di non unire questi thread per nome, tuttavia in questo modo sto cambiando il codice di produzione per far fronte a questo e non sono troppo entusiasta di questa soluzione. Qualcun altro l'ha già incontrato e ha trovato una buona soluzione? Qualsiasi aiuto in questo sarebbe molto apprezzato. Di seguito è riportato un codice di esempio per il problema.

Esempio test_process.py

import sys 
import traceback 
import unittest 

class TestUBProcessManager(unittest.TestCase): 
    def setUp(self): 
     pass 

    def runTest(self): 
     globalsDict = {'sys':sys, '__name__':'__main__'} 

     haveException = False 
     try: 
      execfile('Process.py', globalsDict) 
     except Exception, detail: 
      haveException = True 
      traceback.print_exc() 

     self.assertFalse(haveException) 

if __name__ == '__main__': 
    unittest.main()  

Esempio Process.py

import threading                          
import time                           

class ThreadClass(threading.Thread):                     

    def __init__(self, threadName, threadRunCount,threadSleep):              
     threading.Thread.__init__(self)                    
     self.name = threadName;                      
     self.runCount = threadRunCount;                    
     self.sleepTime = threadSleep;                    

    def run(self):                         
     for i in range (1,self.runCount):                   
      print "\t",self.name, "Working";                   
      time.sleep(self.sleepTime);                    

class Launcher(object):                        
    def __init__(self):                        
     print "Init Threads";                      
     self.threadA = ThreadClass("Thread A",3,2)                 
     self.threadB = ThreadClass("Thread B",7,2)                 

    def launchProcess(self):                       
     print "Starting Threads";                     
     self.threadA.start();                      
     self.threadB.start();                      
     time.sleep(2);                        

if __name__ == '__main__':                       
    launcher = Launcher()                       
    try:                            
     launcher.launchProcess()                      
    finally:                           
     print "Available Threads Needed To Finish"                 
     for t in threading.enumerate():                    
      print "Thread: ",t.getName                    

     print "Attempt to join threads to ensure all threads are finished"           
     for t in threading.enumerate():                    
      print "About To Join : ",t.getName                  
      if t.getName() != 'MainThread':                   
        t.join()                       
    print "All Done"                         

risposta

3

Solo in caso qualcun altro arriva incontrato questo problema. Ho deciso di cambiare il mio codice per verificare quali thread sono presenti all'avvio del test.

if __name__ == '__main__':                       
    initialThreads = [];  
    for t in threading.enumerate(): 
     initialThreads.append(t); 

    launcher = Launcher()                       
    try:                            
     launcher.launchProcess()                      
    finally:                           
     print "Available Threads Needed To Finish"                 
     for t in threading.enumerate():                    
     print "Thread: ",t.getName                    

     print "Attempt to join threads to ensure all threads are finished"           
     for t in threading.enumerate():                    
      print "About To Join : ",t.getName                  
      if t not in initialThreads:                   
       t.join()                       
    print "All Done"   
+0

Aveva questo problema esatto con il test dell'unità in Odoo 8 (OpenERP). Quando si ferma, tenta di unire tutti i thread e si blocca su qualche thread aggiuntivo aggiunto da Eclipse. Nel mio caso, era un singolo ServerComm. Ho aggiunto le tue condizioni extra e ora funziona bene. Grazie mille :) – Jerther

+0

Lo stesso problema con Odoo 10. Ecco un problema relativo a questo Ho inviato al progetto PyDev Debugger su github: https://github.com/fabioz/PyDev.Debugger/issues/84 – Jerther

Problemi correlati