GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Erzwingen Sie das Leeren des Ausgabepuffers im laufenden Programm

WENN Wenn jemand diese Daten wirklich haben möchte, würde ich vorschlagen, die gdb anzuhängen Debugger an den Python-Interpreter, stoppt vorübergehend die Aufgabe und ruft fsync(1) auf (stdout ), trennen Sie sich davon (setzen Sie den Prozess fort) und sehen Sie sich die Ausgabedatei an.

Schauen Sie in /proc/$(pidof python)/fd nach um gültige Dateideskriptoren anzuzeigen. $(pidof x) gibt die PID des Prozesses mit dem Namen 'x zurück '.

# 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

Ich habe diese Methode verwendet, um Arbeitsverzeichnisse zu ändern, Einstellungen im Handumdrehen zu optimieren ... viele Dinge. Leider können Sie nur Funktionen aufrufen, die im laufenden Programm definiert sind, fsync funktioniert aber gut.

(gdb-Befehl 'info functions ' listet alle verfügbaren Funktionen auf. Seien Sie jedoch vorsichtig. Sie arbeiten LIVE in einem Prozess.)

Es gibt auch den Befehl peekfd (gefunden in psmisc Paket auf Debian Jessie und anderen), mit dem Sie sehen können, was sich in den Puffern eines Prozesses verbirgt. Wieder /proc/$(pidof python)/fd zeigt Ihnen gültige Dateideskriptoren, die Sie peekfd als Argumente übergeben können.

Falls Sie sich nicht an -u erinnern für Python können Sie einem Befehl immer stdbuf voranstellen (in coreutils , bereits installiert), um stdin/stdout/stderr wie gewünscht auf ungepuffert, zeilengepuffert oder blockgepuffert zu setzen:

stdbuf -i 0 -o 0 -e 0 python myscript.py > unbuffered.output

Natürlich man pages sind deine Freunde, hey! vielleicht wäre auch hier ein Alias ​​sinnvoll.

alias python='python -u'

Jetzt verwendet Ihr Python immer -u für all Ihre Bemühungen auf der Kommandozeile!


Stellen Sie zunächst sicher, dass Sie die Debugging-Symbole für Python (oder zumindest glibc) haben. Auf Fedora können Sie sie installieren mit:

dnf debuginfo-install python

Hängen Sie dann gdb an zum laufenden Skript und führen Sie die folgenden Befehle aus:

[[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

Dadurch wird stdout geleert und deaktivieren Sie auch die Pufferung. Die 2 aus dem setvbuf call ist der Wert von _IONBF auf meinem System. Sie müssen herausfinden, was auf Ihrem ist (ein grep _IONBF /usr/include/stdio.h sollte reichen).

Basierend auf dem, was ich in der Implementierung von PyFile_SetBufSize gesehen habe und PyFile_WriteString in CPython 2.7 sollte es ziemlich gut funktionieren, aber ich kann keine Garantien abgeben.


Es gibt keine Lösung für Ihr unmittelbares Problem. Wenn Ihr Skript bereits gestartet wurde, können Sie den Puffermodus nicht nachträglich ändern. Dies sind alles In-Memory-Puffer und all das wird eingerichtet, wenn das Skript startet, Datei-Handles geöffnet, Pipes erstellt werden usw.

Kurz gesagt, wenn und nur wenn ein Teil oder die gesamte fragliche Pufferung auf der IO-Ebene bei der Ausgabe erfolgt, könnten Sie einen sync ausführen Befehl; aber das ist in einem solchen Fall im Allgemeinen unwahrscheinlich.

In Zukunft können Sie Pythons -u verwenden Option zum Ausführen des Skripts. Im Allgemeinen haben viele Befehle befehlsspezifische Optionen zum Deaktivieren der stdin/stdout-Pufferung, und Sie können auch mit unbuffer allgemeinen Erfolg haben Befehl von expect Paket.

Eine Strg +C würde dazu führen, dass Puffer auf Systemebene geleert werden, wenn das Programm es sei denn unterbrochen wird die Pufferung wird von Python selbst durchgeführt und es hat nicht die Logik implementiert, um seine eigenen Puffer mit Ctrl zu leeren +C . Ein Suspend, Crash oder Kill wäre nicht so freundlich.

Fordere stdin, stdout und stderr auf, vollständig ungepuffert zu sein.


Linux
  1. Wie kann man auf elegante Weise für immer nichts tun?

  2. Kann Python erkennen, unter welchem ​​Betriebssystem es läuft?

  3. On-the-Fly-Ausgabeumleitung, Anzeige der Dateiumleitungsausgabe, während das Programm noch läuft

  4. Farbausgabe des unter BASH ausgeführten Programms

  5. Python-Programm frisst RAM

Installieren eines Python-Programms unter Linux

Ausführen eines Linux-Befehls von Python

pytest läuft mit einer anderen Version von Python

Python-Code, um zu überprüfen, ob der Dienst ausgeführt wird oder nicht.?

Stellen Sie fest, ob die Ausgabe stdout oder stderr ist

Erhöhen Sie die Puffergröße, während Sie den Bildschirm ausführen