Newsgroup: it.comp.os.linux.sys
Titolo: python subprocess: background + returncode

premessa: lo so, c'è un gruppo python ... mo' scrivo pure lì.
 
Ho un pezzettino di una funzione, che appare proprio come come mostrato di 
seguito:
 
def e_stikazzi()
....
    else:
        print("Loading " + mymap + " ...")
        groovy_load[4] = mymap + ".groovy"
        groovy_log = hvnlcnf.log_prefix + mymap + ".log"
        f = open(groovy_log, "a", bufsize)
        mytime()
        f.write(separator + "Started loading at " + mytimestamp)
        subprocess.Popen(groovy_load, stdout = f, stderr = f)
        f.flush()
        f.close()
 
 
In pratica:
1. f.write scrive qualcosa in un file di log
2. subprocess.Popen lancia un processo in background
3. l'operazione può richiedere tanti minuti, quindi, come da me voluto, il 
processo continua in background, il ciclo gira nuovamente e viene caricato 
il file successivo.
 
Ciò che mi manca è il punto tra 2 e 3 .... chiamiamolo 2,5 :)
 
2,5. catturare il returncode e scrivere qualcosa nel log, quando il 
processo esce *MA* mantenendo il processo sempre in background. 
 
- ho provato a inserire subprocess.wait(), ma il processo va in foreground 
e mi inchioda il terminale fin quando non finisce. 
- ho letto di come potrei usare subprocess.poll() in un loop, fintanto che 
non ritorna qualcosa di diverso da 'None'... però ho come l'impressione 
che il loop mi blocchi nuovamente il terminale (ci devo pensare). 
- usare subprocess.pid() ?? E come? Per che farci? 
- altre idee? Il nostro guru mi suggeriva di provare os.fork... però, 
anche secondo lui, potrebbe non cambiare tanto... secondo voi?

 anche secondo lui, potrebbe non cambiare tanto... secondo voi?
 
os.fork non cambia le cose, visto che è quello che fa subprocess.
 
La soluzione è fare il polling dello stato del processo, ma in modo furbo 
in modo che non ti blocchi il thread principale.
 
Come farlo dipende da come è organizzato il codice.
 
Visto che usi un sistema UNIX, e se devi solo scrivere su un file di log 
qualcosa quando il processo termina, una soluzione semplice è usare i 
segnali per intercettare SIGCHLD.
 
Ma su cosa puoi fare o non fare in un signal handler in Python non sono 
sicuro, dovrei documentarmi.
 
 
Ciao  Manlio

 furbo in modo che non ti blocchi il thread principale.
 
ci penserò su questo punto... 
 

capirà mai come funziona, però funzionerà. 
 
4. Siccome questo mondo e' governato da Murphy, ho letto il tuo messaggio
   prima su it.comp.lang.python e ti ho risposto di la'.
 
5. Siccome mi sono alzato tardi, quando ho visto il subject di QUESTO msg
   mi sono detto "Capperi, ma che e' oggi? Tutti ad avere problemi con il
   returncode di un processo in background?!?"
 
Leonardo
 
-- 
 
Then felt I like some watcher of the skies, when a new planet swims into his ken;
Or like stout Cortez when with eagle eyes, he star'd at the Pacific; and all his men
Look'd at each other with a wild surmise - silent, upon a peak in Darien.

 ci penserò su questo punto...
 
Il polling "giusto" è, IMHO:
 
1) usare i segnali 
2) chiamare il metodo wait in un thread separato
3) fare un polling nel main loop (se hai un main loop),
   sia chiamando il metodo wait in modalità non bloccante, o usando il
   supporto del sistema operativo, se presente
   (ad esempio su FreeBSD kqueue supporta il polling dello stato dei
    processi, su Linux il supporto c'è per select/poll/epoll, usando
    la funzione signalfd)
 
Se sei su un sistema UNIX, non vedo perchè non usare 1.
Se devi supportare anche Windows, "purtroppo" la 2 è la soluzione forse 
migliore.
 
 
Ciao  Manlio


Nonn conosco pyhon ma a livello C si imposta un handler sul segnale 
SIGCHLD
Ricevuto il segnale basta una wait per avere il return code del figlio 
appena terminato
Suppongo che anche in python esista qualcosa del genere
 
 
 
 
 
 
 

    prima su it.comp.lang.python e ti ho risposto di la'. 
 
proverò senz'altro il metodo con il modulo 'thread'! 
Grazie.

    sia chiamando il metodo wait in modalità non bloccante
 
mmh... lanciandolo con il modulo "thread" suggerito dal Leonardo. 
mh, mh..... questa sembrerebbe una soluzione (se non avessi l'influenza 
potrei essere più categoric: è, o non è :)