it-swarm.com.de

Wie stderr in Python umleiten?

Ich möchte alle Ausgaben eines Python-Skripts protokollieren. Ich habe es versucht:

import sys

log = []

class writer(object):
    def write(self, data):
        log.append(data)

sys.stdout = writer()
sys.stderr = writer()

Wenn ich nun "etwas" drucke, wird es protokolliert. Wenn ich zum Beispiel einen Syntaxfehler mache, sage "print 'etwas #", wird es nicht protokolliert - es wird stattdessen in die Konsole gehen.

Wie kann ich auch die Fehler des Python-Interpreters erfassen?

Ich habe hier eine mögliche Lösung gesehen:

http://www.velocityreviews.com/forums/showpost.php?p=1868822&postcount=3

aber das zweite Beispiel meldet sich in/dev/null an - das ist nicht was ich will. Ich möchte es in eine Liste wie mein Beispiel oben oder StringIO oder so einloggen.

Außerdem möchte ich vorzugsweise keinen Unterprozess erstellen (und stdout und stderr in einem separaten Thread lesen).

16
EcirH

Sie können im Python-Code nichts tun, um Fehler beim Kompilieren desselben Codes zu erfassen. Wie könnte es Wenn der Compiler den Code nicht vollständig kompilieren kann, wird der Code nicht ausgeführt, sodass Ihre Umleitung noch nicht in Kraft getreten ist.

Hier kommt Ihr (unerwünschter) Unterprozess ins Spiel. Sie können Python-Code schreiben, der stdout umleitet, und dann den Python-Interpreter aufrufen, um einen anderen Code zu kompilieren.

5
Ned Batchelder

Ich habe eine Software, die ich für die Arbeit geschrieben habe und die stderr in einer Datei wie dieser erfasst:

import sys
sys.stderr = open('C:\\err.txt', 'w')

so ist es definitiv möglich.

Ich glaube, Ihr Problem ist, dass Sie zwei Instanzen des Schreibers erstellen.

Vielleicht etwas mehr wie:

import sys

class writer(object):
    log = []

    def write(self, data):
        self.log.append(data)

logger = writer()
sys.stdout = logger
sys.stderr = logger
19
KingRadical

Ich kann mir keinen einfachen Weg vorstellen. Der Standardfehler des Python-Prozesses befindet sich auf einer niedrigeren Ebene als ein Python-Dateiobjekt (C vs. Python).

Sie können das Python-Skript in ein zweites Python-Skript einschließen und subprocess.Popen verwenden. Es ist auch möglich, dass Sie in einem einzigen Skript etwas Magie wie diese ziehen:

import os
import subprocess
import sys

cat = subprocess.Popen("/bin/cat", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
os.close(sys.stderr.fileno())
os.dup2(cat.stdin.fileno(), sys.stderr.fileno())

Verwenden Sie dann select.poll (), um cat.stdout regelmäßig zu überprüfen, um die Ausgabe zu finden.

Ja, das scheint zu funktionieren.

Das Problem, das ich voraussage, ist, dass meistens etwas, das per Python auf stderr gedruckt wird, bedeutet, dass es bald beendet wird. Der üblichere Weg, dies zu handhaben, wäre über Ausnahmen.

---------Bearbeiten

Irgendwie habe ich die os.pipe () - Funktion vermisst.

import os, sys
r, w = os.pipe()
os.close(sys.stderr.fileno())
os.dup2(w, sys.stderr.fileno())

Dann von r lesen

6
user227667

Wenn Sie Linux/Mac OS verwenden, können Sie dazu einfach die Dateiumleitung verwenden. Wenn Sie beispielsweise "a.py" ausführen und alle Nachrichten, die es generiert, in der Datei "a.out" aufzeichnen, wäre dies einfach der Fall

python a.py 2>&1 > a.out

Der erste Teil leitet stderr an stdout um, und der zweite Teil leitet das an eine Datei namens a.out weiter.

Eine längere Liste von Umleitungsoperatoren in Linux/Unix finden Sie unter https://askubuntu.com/questions/420981/how-do-i-save-terminal-output-to-a-file

4
VitleysingurQ

Python führt Ihren Code nicht aus, wenn ein Fehler vorliegt. Sie können Ihr Skript aber auch in ein anderes Skript importieren. Beispiel:

Script.py

print 'something#

FinalScript.py

from importlib.machinery import SourceFileLoader

try:
    SourceFileLoader("main", "<SCRIPT PATH>").load_module()
except Exception as e:
    # Handle the exception here
0
ColdGrub1384
import sys
import tkinter

# ********************************************

def mklistenconsswitch(*printf: callable) -> callable:
    def wrapper(*fcs: callable) -> callable:
        def newf(data):
            [prf(data) for prf in fcs]
        return newf
    stdoutw, stderrw = sys.stdout.write, sys.stderr.write
    funcs = [(wrapper(sys.stdout.write, *printf), wrapper(sys.stderr.write, *printf)), (stdoutw, stderrw)]
    def switch():
        sys.stdout.write, sys.stderr.write = dummy = funcs[0]
        funcs[0] = funcs[1]
        funcs[1] = dummy
    return switch

# ********************************************

def datasupplier():
    i = 5.5
    while i > 0:
        yield i
        i -= .5

def testloop():
    print(supplier.__next__())
    svvitch()
    root.after(500, testloop)

root = tkinter.Tk()
cons = tkinter.Text(root)
cons.pack(fill='both', expand=True)
supplier = datasupplier()
svvitch = mklistenconsswitch(lambda text: cons.insert('end', text))
testloop()
root.mainloop()
0
yagami raito

Seit Python 3.5 können Sie contextlib.redirect_stderr verwenden.

with open('help.txt', 'w') as f:
    with redirect_stdout(f):
        help(pow)
0
max

Um Neds Antwort hinzuzufügen, ist es schwierig, die Fehler während der Kompilierung im laufenden Betrieb zu erfassen.

Sie können mehrere Druckanweisungen in Ihr Skript schreiben und Sie können stdout in eine Datei schreiben. Wenn der Fehler auftritt, wird das Schreiben in die Datei gestoppt. Um den Code zu debuggen, können Sie die zuletzt protokollierte Ausgabe überprüfen und Ihr Skript danach überprüfen.


Etwas wie das:

# Add to the beginning of the script execution(eg: if __== "__main__":).
from datetime import datetime
dt = datetime.now()
script_dir = os.path.dirname(os.path.abspath(__file__))      # gets the path of the script
stdout_file = script_dir+r'\logs\log'+('').join(str(dt.date()).split("-"))+r'.log'
sys.stdout = open(stdout_file, 'w')

Dadurch wird eine Protokolldatei erstellt und die Druckanweisungen in die Datei übertragen.


Anmerkung: Achten Sie auf Escapezeichen in Ihrem Dateipfad, während Sie mit script_dir in der zweiten Zeile der letzten Zeile im Code verketten. Möglicherweise möchten Sie etwas Ähnliches wie eine rohe Zeichenfolge. Sie können diesen Thread dazu überprüfen.

0
rzskhr