SE uno volesse davvero quei dati, suggerirei di allegare il gdb debugger all'interprete python, interrompendo momentaneamente l'attività, chiamando fsync(1)
(stdout ), staccati da esso (riprendendo il processo) e vai a esaminare il file di output.
Cerca in /proc/$(pidof python)/fd
per visualizzare descrittori di file validi. $(pidof x)
restituisce il PID del processo denominato 'x
'.
# your python script is running merrily over there.... with some PID you've determined.
#
# load gdb
gdb
#
# attach to python interpreter (use the number returned by $(pidof python))
attach 1234
#
# force a sync within the program's world (1 = stdout, which is redirected in your example)
call fsync(1)
#
# the call SHOULD have returned 0x0, sync successful. If you get 0xffffffff (-1), perhaps that wasn't stdout. 0=stdin, 1=stdout, 2=stderr
#
# remove our claws from poor python
detach
#
# we're done!
quit
Ho usato questo metodo per cambiare directory di lavoro, modificare le impostazioni al volo... molte cose. Purtroppo, puoi chiamare solo funzioni che sono definite nel programma in esecuzione, fsync
funziona bene però.
(comando gdb 'info functions
' elencherà tutte le funzioni disponibili. Stai attento però. Stai operando DAL VIVO su un processo.)
C'è anche il comando peekfd
(si trova in psmisc
pacchetto su Debian Jessie e altri) che ti permetterà di vedere cosa si nasconde nei buffer di un processo. Di nuovo, /proc/$(pidof python)/fd
ti mostrerà descrittori di file validi da dare come argomenti a peekfd.
Se non ricordi -u
per python, puoi sempre prefissare un comando con stdbuf
(in coreutils
, già installato) per impostare stdin/stdout/stderr su unbuffered, line buffered o block buffered come desiderato:
stdbuf -i 0 -o 0 -e 0 python myscript.py > unbuffered.output
Certo, man pages
sono tuoi amici, ehi! forse un alias potrebbe essere utile anche qui.
alias python='python -u'
Ora il tuo pitone usa sempre -u
per tutti i tuoi sforzi da riga di comando!
Per prima cosa assicurati di avere i simboli di debug per Python (o almeno glibc). Su Fedora puoi installarli con:
dnf debuginfo-install python
Quindi allega gdb allo script in esecuzione ed eseguire i seguenti comandi:
[[email protected] ~]$ pidof python2
9219
[[email protected] ~]$ gdb python2 9219
GNU gdb (GDB) Fedora 7.7.1-13.fc20
...
0x00007fa934278780 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
81 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) call fflush(stdout)
$1 = 0
(gdb) call setvbuf(stdout, 0, 2, 0)
$2 = 0
(gdb) quit
A debugging session is active.
Inferior 1 [process 9219] will be detached.
Quit anyway? (y or n) y
Detaching from program: /usr/bin/python2, process 9219
Questo cancellerà stdout e disabilita anche il buffering. Il 2
dal setvbuf
call è il valore di _IONBF
sul mio sistema. Dovrai scoprire cosa c'è nel tuo (un grep _IONBF /usr/include/stdio.h
dovrebbe funzionare).
Sulla base di ciò che ho visto nell'implementazione di PyFile_SetBufSize
e PyFile_WriteString
in CPython 2.7, dovrebbe funzionare abbastanza bene, ma non posso dare alcuna garanzia.
Non c'è soluzione al tuo problema immediato. Se il tuo script è già iniziato, non puoi modificare la modalità di buffering dopo il fatto. Questi sono tutti buffer in memoria e tutto ciò viene impostato all'avvio dello script, all'apertura degli handle di file, alla creazione di pipe, ecc.
Come azzardo, se e solo se parte o tutto il buffering in questione viene eseguito a livello di IO sull'output, potresti eseguire un sync
comando; ma questo è generalmente improbabile in un caso come questo.
In futuro potrai usare -u
di Python opzione per eseguire lo script. In generale, molti comandi hanno opzioni specifiche per disabilitare il buffering stdin/stdout e potresti anche avere qualche successo generico con unbuffer
comando dal expect
pacchetto.
Un Ctrl +C causerebbe lo svuotamento dei buffer a livello di sistema quando il programma viene interrotto a meno che il buffering è fatto da Python stesso e non ha implementato la logica per svuotare i propri buffer con Ctrl +C . Una sospensione, un crash o un kill non sarebbero così gentili.
Forza stdin, stdout e stderr per essere totalmente unbuffered.