KDYŽ kdo opravdu chtěl tato data, navrhoval bych připojit gdb debugger na interpret pythonu, na chvíli zastaví úlohu, zavolá fsync(1)
(stdout ), oddělte se od něj (obnovte proces) a přejděte na výstupní soubor.
Podívejte se do /proc/$(pidof python)/fd
zobrazíte platné deskriptory souborů. $(pidof x)
vrátí PID procesu s názvem '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
Použil jsem tuto metodu ke změně pracovního adresáře, vyladění nastavení za běhu... mnoho věcí. Bohužel můžete volat pouze funkce, které jsou definovány ve spuštěném programu fsync
funguje dobře.
(příkaz gdb 'info functions
' zobrazí seznam všech dostupných funkcí. Buďte však opatrní. Provozujete ŽIVĚ na procesu.)
Existuje také příkaz peekfd
(nalezeno v psmisc
balíček na Debianu Jessie a další), což vám umožní vidět, co se skrývá v bufferech procesu. Opět /proc/$(pidof python)/fd
vám ukáže platné deskriptory souborů, které můžete zadat jako argumenty pro peekfd.
Pokud si nepamatujete -u
pro python můžete vždy před příkazem uvést stdbuf
(v coreutils
, již nainstalovaný) a nastavte stdin/stdout/stderr na bez vyrovnávací paměti, s řádkovou vyrovnávací pamětí nebo s blokovou vyrovnávací pamětí podle potřeby:
stdbuf -i 0 -o 0 -e 0 python myscript.py > unbuffered.output
Samozřejmě, man pages
jsou vaši přátelé, hej! možná by se zde také mohl hodit alias.
alias python='python -u'
Nyní váš python vždy používá -u
za všechny vaše snahy o příkazový řádek!
Nejprve se ujistěte, že máte ladicí symboly pro Python (nebo alespoň glibc). Na Fedoře je můžete nainstalovat pomocí:
dnf debuginfo-install python
Poté připojte gdb na spuštěný skript a spusťte následující příkazy:
[[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
Tím dojde k vyprázdnění stdout a také zakázat ukládání do vyrovnávací paměti. 2
z setvbuf
call je hodnota _IONBF
na mém systému. Budete muset zjistit, co je na vašem (grep _IONBF /usr/include/stdio.h
měl by stačit).
Na základě toho, co jsem viděl při implementaci PyFile_SetBufSize
a PyFile_WriteString
v CPythonu 2.7 by to mělo fungovat docela dobře, ale nemohu poskytnout žádné záruky.
Na váš bezprostřední problém neexistuje žádné řešení. Pokud se váš skript již spustil, nemůžete poté režim ukládání do vyrovnávací paměti změnit. To vše jsou vyrovnávací paměti v paměti a vše se nastavuje při spuštění skriptu, otevírání popisovačů souborů, vytváření kanálů atd.
Stručně řečeno, pokud a pouze v případě, že se některé nebo všechny dotyčné ukládání do vyrovnávací paměti provádí na úrovni IO na výstupu, můžete provést sync
příkaz; ale to je obecně nepravděpodobné v případě jako je tento.
V budoucnu můžete použít -u
Pythonu možnost spuštění skriptu. Obecně platí, že mnoho příkazů má možnosti specifické pro příkazy k deaktivaci ukládání do vyrovnávací paměti stdin/stdout a také můžete mít nějaký obecný úspěch s unbuffer
příkaz z expect
balíček.
A Ctrl +C by způsobilo vyprázdnění vyrovnávacích pamětí na úrovni systému, když je program přerušen pokud ukládání do vyrovnávací paměti provádí sám Python a neimplementoval logiku pro vyprázdnění vlastních vyrovnávacích pamětí pomocí Ctrl +C . Pozastavení, havárie nebo zabití by nebylo tak laskavé.
Vynutit, aby stdin, stdout a stderr byly zcela bez vyrovnávací paměti.