SI uno realmente quería esos datos, sugeriría adjuntar el gdb depurador al intérprete de python, deteniendo momentáneamente la tarea, llamando a fsync(1)
(salida estándar ), sepárelo (reanudando el proceso) y examine el archivo de salida.
Mira en /proc/$(pidof python)/fd
para ver los descriptores de archivo válidos. $(pidof x)
devuelve el PID del proceso llamado '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
He usado este método para cambiar los directorios de trabajo, ajustar la configuración sobre la marcha... muchas cosas. Por desgracia, solo puede llamar a funciones que están definidas en el programa en ejecución, fsync
aunque funciona bien.
(comando gdb 'info functions
' mostrará una lista de todas las funciones disponibles. Sin embargo, ten cuidado. Estás operando EN VIVO en un proceso).
También existe el comando peekfd
(encontrado en psmisc
paquete en Debian Jessie y otros) que le permitirá ver lo que se esconde en los búferes de un proceso. De nuevo, /proc/$(pidof python)/fd
le mostrará descriptores de archivo válidos para dar como argumentos a peekfd.
Si no recuerda -u
para python, siempre puede anteponer un comando con stdbuf
(en coreutils
, ya instalado) para establecer stdin/stdout/stderr en sin búfer, con búfer de línea o con búfer de bloque, según se desee:
stdbuf -i 0 -o 0 -e 0 python myscript.py > unbuffered.output
Por supuesto, man pages
son tus amigos, hey! quizás un alias podría ser útil aquí también.
alias python='python -u'
Ahora tu python siempre usa -u
para todos sus esfuerzos de línea de comandos!
Primero asegúrese de tener los símbolos de depuración para Python (o al menos glibc). En Fedora puede instalarlos con:
dnf debuginfo-install python
Luego adjunte gdb al script en ejecución y ejecute los siguientes comandos:
[[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
Esto vaciará stdout y también desactivar el almacenamiento en búfer. El 2
del setvbuf
call es el valor de _IONBF
en mi sistema Deberá averiguar qué hay en el suyo (un grep _IONBF /usr/include/stdio.h
debería hacer el truco).
Basado en lo que he visto en la implementación de PyFile_SetBufSize
y PyFile_WriteString
en CPython 2.7, debería funcionar bastante bien, pero no puedo garantizar nada.
No hay solución a su problema inmediato. Si su secuencia de comandos ya comenzó, no puede cambiar el modo de almacenamiento en búfer después del hecho. Todos estos son búferes en memoria y todo eso se configura cuando se inicia el script, se abren los identificadores de archivos, se crean conductos, etc.
Como posibilidad remota, si y solo si parte o la totalidad del almacenamiento en búfer en cuestión se realiza en el nivel de IO en la salida, podría hacer un sync
dominio; pero esto es generalmente poco probable en un caso como este.
En el futuro, puede usar -u
de Python opción para ejecutar el script. En general, muchos comandos tienen opciones específicas de comando para deshabilitar el almacenamiento en búfer de stdin/stdout, y también puede tener cierto éxito genérico con el unbuffer
comando desde el expect
paquete.
Un Ctrl +C haría que los búferes a nivel del sistema se vaciaran cuando el programa se interrumpa a menos que el almacenamiento en búfer lo realiza Python mismo y no ha implementado la lógica para vaciar sus propios búferes con Ctrl +C . Una suspensión, bloqueo o eliminación no sería tan amable.
Obligar a stdin, stdout y stderr a estar totalmente sin búfer.