Ho uno script SGE per eseguire un codice Python, inviato alla coda usando qsub. Nello script python, ho alcune istruzioni di stampa (aggiornandomi sullo stato di avanzamento del programma). Quando eseguo lo script python dalla riga di comando, le istruzioni di stampa vengono inviate allo stdout. Per lo script sge, utilizzo l'opzione -o per reindirizzare l'output su un file. Tuttavia, sembra che lo script li invierà al file solo dopo che lo script Python ha completato l'esecuzione. Ciò è fastidioso perché (a) non riesco più a visualizzare gli aggiornamenti in tempo reale sul programma e (b) se il mio lavoro non termina correttamente (ad esempio se il mio lavoro viene espulso dalla coda) nessuno degli aggiornamenti viene stampato. Come posso assicurarmi che lo script stia scrivendo sul file ogni volta che voglio stampare qualcosa, invece di rimetterlo insieme alla fine?Script SGE: stampa su file durante l'esecuzione (non solo alla fine)?
risposta
Penso che si stia verificando un problema con l'output bufferizzato. Python usa una libreria per gestire il suo output e la libreria sa che è più efficiente scrivere un blocco in un momento in cui non sta parlando con un tty.
Ci sono un paio di modi per ovviare a questo problema. È possibile eseguire python con l'opzione "-u" (vedi la pagina man pitone per i dettagli), per esempio, con qualcosa di simile come la prima linea del vostro script:
#! /usr/bin/python -u
ma questo non funziona se stai usando il trucco "/ usr/bin/env" perché non sai dove è installato python.
Un altro modo è quello di riaprire lo stdout con qualcosa di simile:
import sys
import os
# reopen stdout file descriptor with write mode
# and 0 as the buffer size (unbuffered)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
Nota il parametro bufsize di os.fdopen essere impostato a 0 per costringerlo ad essere senza buffer. Puoi fare qualcosa di simile con sys.stderr.
Ho appena riscontrato un problema simile con SGE e nessun suggested method in "unbuffer" il file IO sembrava funzionare per me. Ho dovuto aspettare fino alla fine dell'esecuzione del programma per vedere qualsiasi output.
La soluzione che ho trovato era di avvolgere sys.stdout in un oggetto personalizzato che reimplementa il metodo "write". Invece di scrivere effettivamente su stdout, questo nuovo metodo apre invece il file in cui viene reindirizzato IO, aggiunge i dati desiderati e quindi chiude il file. È un po 'brutto, ma ho trovato risolto il problema, poiché l'effettiva apertura/chiusura del file costringe l'IO ad essere interattivo.
Ecco un esempio minimo:
import os, sys, time
class RedirIOStream:
def __init__(self, stream, REDIRPATH):
self.stream = stream
self.path = REDIRPATH
def write(self, data):
# instead of actually writing, just append to file directly!
myfile = open(self.path, 'a')
myfile.write(data)
myfile.close()
def __getattr__(self, attr):
return getattr(self.stream, attr)
if not sys.stdout.isatty():
# Detect redirected stdout and std error file locations!
# Warning: this will only work on LINUX machines
STDOUTPATH = os.readlink('/proc/%d/fd/1' % os.getpid())
STDERRPATH = os.readlink('/proc/%d/fd/2' % os.getpid())
sys.stdout=RedirIOStream(sys.stdout, STDOUTPATH)
sys.stderr=RedirIOStream(sys.stderr, STDERRPATH)
# Simple program to print msg every 3 seconds
def main():
tstart = time.time()
for x in xrange(10):
time.sleep(3)
MSG = ' %d/%d after %.0f sec' % (x, args.nMsg, time.time()-tstart)
print MSG
if __name__ == '__main__':
main()
Questo è SGE buffer l'output del processo, succede se il suo un processo di pitone o di qualsiasi altro.
In generale è possibile ridurre o disabilitare il buffering in SGE modificandolo e ricompilando. Ma non è una gran cosa da fare, tutti i dati verranno scritti lentamente sul disco e influenzeranno le tue prestazioni generali.
questo funziona per me:
class ForceIOStream:
def __init__(self, stream):
self.stream = stream
def write(self, data):
self.stream.write(data)
self.stream.flush()
if not self.stream.isatty():
os.fsync(self.stream.fileno())
def __getattr__(self, attr):
return getattr(self.stream, attr)
sys.stdout = ForceIOStream(sys.stdout)
sys.stderr = ForceIOStream(sys.stderr)
e la questione ha a che fare con NFS non sincronizzazione dei dati al master fino a quando un file viene chiuso o fsync viene chiamato.
Come altri hanno accennato, è per motivi di prestazioni non sempre scrivere lo stdout quando non è collegato a un tty.
Se si dispone di un punto specifico in cui si desidera lo stdout da scrivere, è possibile forzare che utilizzando
import sys
sys.stdout.flush()
in quel punto.
Perché non stampare su un file anziché su stdout?
outFileID = open('output.log','w')
print(outFileID,'INFO: still working!')
print(outFileID,'WARNING: blah blah!')
e utilizzare
tail -f output.log
mi ha colpito questo stesso problema di oggi e risolto il programma semplicemente con la scrittura su disco, invece di stampa:
with open('log-file.txt','w') as out:
out.write(status_report)
- 1. Come si esegue un'attività "fine alla fine" ma solo alla fine dell'attività corrente?
- 2. Script di shell con file jar alla fine
- 3. letture Python solo alla fine del testo lima enorme
- 4. script di Unix aggiunge^M alla fine di ogni riga
- 5. linee di stampa in file dalla riga partita fino alla fine del file di
- 6. Symfony2 app_dev.php solo errore 500 Fine prematura dello script
- 7. PyCharm fine stampa = '\ r' affermazione non lavora
- 8. Come andare alla fine del file?
- 9. Uguale alla fine del nome file
- 10. Errore inaspettato alla fine del file
- 11. Log4j non stampa su file o stdout
- 12. aggiungere solo uno script alla testa se non esiste
- 13. Vim show newline alla fine del file
- 14. Stampa dell'output di script php nel file
- 15. aggiungi testo alla fine del file
- 16. zecche solo all'inizio e alla fine di un asse
- 17. Git sovrascrive i file durante una stampa - non mostra conflitti
- 18. Stampa solo l'ultima riga di un file?
- 19. Stampa su terminale durante l'utilizzo del buffer di output negli script PHP CLI
- 20. Scrive fwrite alla fine del file dopo aver cercato fino alla fine
- 21. Stampa su un file o stampa su shell in Perl
- 22. Incluso .cpp alla fine del file di intestazione del modello
- 23. pitone: rimuovere sottostringa solo alla fine della stringa di
- 24. C# - SqlConnection InfoMessage innescando solo alla fine dell'esecuzione
- 25. Stampa solo le parti che corrispondono alla regex
- 26. Rails Rake Task, emette un messaggio durante e alla fine
- 27. Python 2.7: Stampa su file
- 28. UIWebView non scorrerà fino alla fine/fondo
- 29. Stampa matrice su un file
- 30. Stampa su stdout e file contemporaneamente
Grazie! Non sapevo che questo avesse qualcosa a che fare con Python. Anche trovato questo post utile http://stackoverflow.com/questions/107705/python-output-buffering – miz