2016-06-07 21 views
7

Si tratta di un follow-up a https://stackoverflow.com/questions/37684111/ironpython-exe-file-closing-immediately-no-exception-thrownPython Threading.Timer oggetto non funziona quando viene compilato a .exe

ho capito che il mio programma non funziona, una volta compilato a causa di un problema con l'oggetto Timer nella libreria di threading. Ho incluso la libreria nella mia directory \ Lib \ site-packages e ho aggiunto la directory al percorso nel programma. Ecco il codice di prova che sto utilizzando - un semplice programma di conteggio:

import sys 
from threading import Timer 

sys.path.append('C:\Users\[user]\Documents\Visual Studio 2015\Projects\Testing Timer Compilation issue\Testing Timer Compilation issue') 
sys.path.append('C:\Users\[user]\Documents\Visual Studio 2015\Projects\Testing Timer Compilation issue\Testing Timer Compilation issue\Lib') 

class Chron(): 
    def __init__(self): 
     self.t = Timer(2, self.count) 
     self.t.start() 
     self.i = 0 

    def count(self): 
     print(self.i) 
     self.i += 1 
     if self.i <= 15: 
      self.t = Timer(2, self.count) 
      self.t.start() 

c = Chron() 

funziona perfettamente in interprete interattivo all'interno di Visual Studio, ma una volta che uso pyc.py per compilare un file exe, non sarà eseguito e si chiude semplicemente dopo ~ 5 secondi, senza eccezioni lanciate.

Come accennato nella domanda precedente, ho un programma con un Timer in esso che ho bisogno di compilare, in quanto il codice sorgente contiene credenziali sensibili. Ci sono trucchi necessari per far funzionare il Timer all'interno di un exe? È semplicemente incompatibile?

Modifica: 6 giorni senza risposta. Sfortunatamente, non sembrano esserci risorse per questo specifico problema da nessuna parte su Internet. È quasi come se fossi l'unico ad avere questo problema. Questo mi sembra strano, dal momento che il problema sembra essere con l'oggetto Timer stesso, e non posso immaginare che nessun altro abbia provato a distribuire un'applicazione con un Timer al suo interno. Qualsiasi intuizione sarebbe utile a questo punto, poiché sono completamente perplesso.

+0

Hai provato a lasciare le stampe nel codice per vedere dove si ferma esattamente? Potrebbe essere utile per rintracciare il problema – Nikign

+0

Ecco come sono arrivato dove sono attualmente. Nella mia domanda precedente, che ho linkato sopra, vedrete che questa domanda è in realtà il prodotto di fare proprio questo su un pezzo di codice molto più complesso. Questo rompe il secondo in cui tenta di avviare il conteggio del timer. – Inagnikai

+0

in modo che non entri nella funzione di avvio? Forse c'è qualcosa nella funzione start – Nikign

risposta

5

Il problema è che si sta facendo affidamento sull'interprete Python sottostante per gestire con garbo il caso in cui è terminato il thread principale del file eseguibile, ma altri dovrebbero essere ancora in esecuzione.

L'esecuzione del codice direttamente con CPython o IronPython funziona come previsto. Gli oggetti Timer che crei sono in realtà una specializzazione di un Thread. L'interprete riconosce che ci sono dei thread non-daemon ancora attivi e quindi non si chiude. Vedere the docs per una spiegazione dei thread daemon se non si conosce la differenza tra i 2 tipi di Thread.

Tuttavia, quando si esegue come un eseguibile, sembrerebbe che il codice che IronPython utilizza per avvolgere l'interprete non sia così gentile. Aspetta solo che il thread principale termini e poi chiuda tutto. Ciò accade nonostante il fatto che i tuoi Timer siano dichiarati come thread non demone. Probabilmente si tratta di un bug in IronPython.

La soluzione è quindi di lasciare il thread principale in esecuzione mentre i thread del timer sono ancora in funzione. Il modo più semplice per farlo per questo codice di esempio è solo per dormire - per esempio:

import sys 
sys.path.append(r"c:\Program Files (x86)\IronPython 2.7\Lib") 
from threading import Timer 
from time import sleep 

class Chron(): 
    def __init__(self): 
     self.t = Timer(2, self.count) 
     self.t.start() 
     self.i = 0 

    def count(self): 
     print(self.i) 
     self.i += 1 
     if self.i <= 15: 
      self.t = Timer(2, self.count) 
      self.t.start() 

c = Chron() 
sleep(35) 

Tuttavia, per le applicazioni più complesse, si dovrebbe prendere in considerazione le comunicazioni fra i thread di coordinare, quando per chiudere - per esempio utilizzando join() per attendere la terminazione del thread.

+0

Poiché 'threading.Timer' sottoclasse' threading.Thread', potrebbe essere un'altra soluzione da fare ['self.t.daemon = True'] (https://docs.python.org/2/library/threading.html# threading.Thread.daemon) prima di chiamare 'self.t.start()'? –

+1

@StevenRumbalski Bella idea, ma pensa di aver sbagliato la logica ... Impostandola su Vero significa che l'Interprete può ignorare questo Thread/Timer! Cercando in alto, si impostano su False, quindi non penso che questo possa risolverlo ... –

+0

Sì, hai ragione. Ma per quanto riguarda l'impostazione predefinita, si impostano automaticamente sullo stato del thread principale. È possibile che Iron Python abbia impostato il thread principale in modo errato? –

Problemi correlati