/ / Echtzeitausgabe eines Python-Skripts unter Verwendung von subprozess.Popen () - python, subprozess

Echtzeitausgabe eines Python-Skripts mit subprozess.Popen () - python, subprozess

Nach dem Durchsuchen habe ich eine Funktion definiert, um den Befehl wie in terminal auszuführen:

import shlex
import subprocess
def execute_cmd(cmd):
p = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)

for line in iter(p.stdout.readline, b""):  # b"" here for python3
sys.stdout.write(line.decode(sys.stdout.encoding))

error = p.stderr.read().decode()
if error:
raise Exception(error)

Es funktioniert gut (Ausgabe ist Echtzeit), wenn i

execute_cmd("ping -c 5 www.google.com")

Jedoch wenn ich benutze execute_cmd Um ein Python-Skript auszuführen, wird die Ausgabe gedruckt, bis der Vorgang abgeschlossen ist.

execute_cmd("python test.py")

Skript: test.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time

print("hello")
time.sleep(2)
print("hello, again")

Wie kann ich es reparieren? Vielen Dank!


Es tut mir leid, dass ich nicht erklärt habe, warum "das stdout erwischtund dann schreibe ich es wieder in stdout ". Hier möchte ich wirklich Skriptausgänge in Logger einfangen, der Logger in Bildschirm (StreamHandler) und Protokolldatei (FileHandler) ausgeben "Teil. Und ignorieren Sie die stdout= Parameter scheint nicht zu funktionieren.

Pipeline:

  1. Setup-Logger;
  2. STDOUT, STDERR zum Logger umleiten;
  3. Skripte ausführen;

Wegen Schritt 2, wenn ich ignoriere stdout= In diesem Parameter werden die Ausgaben der Skripts weiterhin an STDOUT ausgegeben und werden nicht in der Datei protokolliert.

Vielleicht kann ich setzen stdout= zum Logger

Antworten:

1 für die Antwort № 1

Dies ist ein häufiges Problem des zugrunde liegenden Ausgabesystems, insbesondere unter Linux oder anderen Unix-ähnlichen Systemen. Die io-Bibliothek ist intelligent genug, um die Ausgabe auf jede zu leeren n Wenn er feststellt, dass die Ausgabe an a gerichtet istTerminal. Diese automatische Spülung tritt jedoch nicht auf, wenn die Ausgabe in eine Datei oder eine Pipe umgeleitet wird, möglicherweise aus Leistungsgründen. Es ist nicht wirklich ein Problem, wenn nur die Daten von Bedeutung sind, aber es führt zu merkwürdigem Verhalten, wenn auch das Timing wichtig ist.

Leider kenne ich keine einfache Möglichkeit, das Programm vom Aufrufer (*) zu beheben. Die einzige Möglichkeit besteht darin, die Aufgeräumungskraft für jede Zeile / jeden Block zu leeren oder eine ungepufferte Ausgabe zu verwenden:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import sys

print("hello")
sys.stdout.flush()
time.sleep(2)
print("hello, again")

(*) Der kugelsichere Weg wäre die Verwendung von aPseudo-Terminal. Der Anrufer steuert die Masterseite und übergibt die Clientseite an den Angerufenen. Die Bibliothek erkennt ein Terminal und wird in jeder Zeile automatisch geleert. Aber außerhalb der Unix-Welt ist es nicht mehr portabel und nicht wirklich eine einfach Weg.