Gleichzeitige Ausgabe auf Bildschirm und Datei

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
ArtS
User
Beiträge: 3
Registriert: Mittwoch 22. Juli 2009, 15:35

Hallo liebes Forum,

ich bin ein Python-Neuling und würde gerne wissen, ob es eine elegante Methode gibt, z.B. einen String gleichzeitig auf dem Bildschirm und in eine Datei auszugeben.
Ich muss nämlich ein Skript schreiben, bei dem alle Programmschritte in einer Logfile dokumentiert und teilweise zusätzlich auf dem Bildschirm ausgegeben werden müssen.

Gruß

ArtS
problembär

Wie würdest Du denn die unelegante Methode schreiben?
ArtS
User
Beiträge: 3
Registriert: Mittwoch 22. Juli 2009, 15:35

Ein unelegante Methode wäre meiner Meinung nach, den String erst mit dem Print-Befehl auf dem Bildschirm auszugeben und dann den gleichen String nochmal mit der write-Methode in die Datei zu schreiben.
Es sind wirklich viele Strings, die ich so verarbeiten müsste.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dann schreib doch eine Funktion, die genau das macht.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
ArtS
User
Beiträge: 3
Registriert: Mittwoch 22. Juli 2009, 15:35

Ok, stimmt, ich könnte den String natürlich als Parameter übergeben und die Funktion erledigt die doppelte Ausgabe.
Ich dachte nur, es gebe irgendeine pythoninterne Lösung.
Aber danke schon mal.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Du könntest logging benutzen.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Oder durch Umleiten des stdouts an eine eigene Klasse, die dann diese Aufgabe erledigt. Dann kann ganz normal das print Statement für die Ausgaben verwendet werden:
http://paste.pocoo.org/show/130246/
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

ice2k3 hat geschrieben:Oder durch Umleiten des stdouts an eine eigene Klasse, die dann diese Aufgabe erledigt. Dann kann ganz normal das print Statement für die Ausgaben verwendet werden:
http://paste.pocoo.org/show/130246/
Das hat diverse Probleme, angefangen vom Schreiben auf sys.__stdout__, darüber, dass sinnlose Newlines an text angehängt werden und willkürliche Werte von "text" ausgeschlossen werden, bis hin dazu dass es recht ineffizient ist, die Datei bei jedem write() *dreimal* aufzumachen und wieder zu schließen.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Bei jedem 1000 Mal wird die Datei 3-Mal geöffnet...
Außerdem ist das natürlich spezifisch an meine Anforderungen angepasst. Für ihn müsste er es halt noch modifizieren.

Außerdem wird bei dem normalen stdout auch eine newline angehängt.

Und was ist das Problem mit dem Schreiben auf sys.__stdout__ ?
BlackJack

@ice2k3: `__stdout__` ist "magisch". Das sollte immer an das original `__stdout__` vom Start des Python-Interpretierers gebunden sein. Warum verwendest Du da nicht einfach `sys.stdout`? Das ist die offizielle API die man verwenden sollte.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Sag mal schaut hier keiner den Quelltext genau an bevor er hier nen unqualifizierten Kommentar abgibt. :?
Ich schreibe ja auf den Orginal-__stdout__ mit der ``write`` Methode und genau DAS will ich auch machen...
BlackJack

@ice2k3: Ich habe in den Quelltext geschaut und sehe nicht, warum Du nicht das "originale" `sys.stdout` verwendest. Es ist ja nicht sichergestellt, dass vor Deinem Code ``sys.stdout == `sys.__stdout__`` gilt. Kann ja zum Beispiel auch sein, dass es sich um eine GUI-Anwendung handelt, die vorher schon `sys.stdout` auf ein Objekt umgebogen hat, dass die Ausgaben in einem Textfenster anzeigt. Dann biegst Du die Ausgaben mit Deinem Logger aus Sicht des Anwenders ins Nirwana um.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

ice2k3 hat geschrieben:Bei jedem 1000 Mal wird die Datei 3-Mal geöffnet...
Stimmt, das hab ich falsch interpretiert. Da fällt mir noch auf: `line_count` ist verwirrend, weil write() generell nicht einfach eine Zeile schreibt. Es kann nur einen Teil einer Zeile, oder auch mehrere Zeilen auf einmal schreiben.
Außerdem wird bei dem normalen stdout auch eine newline angehängt.
Aber das ist schon dran, wenn write() aufgerufen wird.
Und was ist das Problem mit dem Schreiben auf sys.__stdout__ ?
Das hat ja BlackJack schon ausgeführt.
Sag mal schaut hier keiner den Quelltext genau an bevor er hier nen unqualifizierten Kommentar abgibt.
Aber nicht doch, sonst wärs ja ein qualifizierter Kommentar...
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
lunar

ice2k3 hat geschrieben:Bei jedem 1000 Mal wird die Datei 3-Mal geöffnet...
Die Datei wird aber immer noch bei jedem Schreibzugriff geöffnet und wieder geschlossen. Das ist ineffizient. Sinnvoller wäre es, dass Dateiobjekt als Exemplarattribut zu setzen.

Und was genau ist der Sinn und Zweck von Zeile zehn? Du öffnest da eine Datei, in die du nichts schreibst ...

Ich persönlich halte es für zweifelhaft, globale Attribute wie sys.stdout so zu manipulieren. Schließlich ist das letztlich nur eine schwache Variante des "logging"-Moduls.
gurke111
User
Beiträge: 28
Registriert: Freitag 26. Oktober 2007, 22:55

Ich hab es früher mal so gelöst:

Code: Alles auswählen

logfilepath = 'log.log'
log_fd = open(logfilepath,'w')
sys.stdout = Tee(sys.stdout, log_fd)
sys.stderr = sys.stdout

class Tee(object):
    """
    Provides a write()-method that writes to two filedescriptors.

    One should be standard-stdout and the other should describe a real file.
    If sys.stdout is replaced with an instance of this `Tee`-class and sys.stderr is
    set to sys.stdout, all stdout+stderr of the script is collected to console and
    to file at the same time.
    """
    def __init__(self, stdout, file):
        self.stdout = stdout
        self.file = file

    def write(self, data):
        self.stdout.write(data)
        try:
          self.file.write(data)
          self.file.flush()
        except:
          pass
Was ich da mit dem try except pass wollte, weiß ich auch nicht mehr so genau.. vermutlich ging es mir darum, dass das Schreiben zum Originalen stdout immer funktioniert und dass mit der Datei ruhig Mist passieren kann. Das wäre sicherlich zu verfeinern :-)
[url]http://gehrcke.de[/url]
python_newbee
User
Beiträge: 2
Registriert: Freitag 25. Mai 2018, 10:17

Hallo Zusammen,
ich hoffe dieses Thema findet noch Beachtung, wenn ich hier eine neue Frage poste.

Ich beschäftige mich ganz frisch mit Python und habe ehrlich nicht viel Ahnung davon.
Jedenfalls möchte ich einen Text, der auf dem Bildschirm ausgegeben wird auch in eine Textdatei speichern. Leider weiß ich nicht so recht, wie das geht.

Hier mal die funktionierende Zeile mit der Bildschirmausgabe:

else:
print(u'file loaded: {}\nMessage: {}'.format(audio_file, response['message']))

und so würde ich es in eine Textdatei speichern:

file = open(path/to/the/file/message.txt, "w+")
file.write(message.text)
file.close()

Nur so funktioniert es leider nicht und ich weiß nicht, wie ich diese Zeilen vernünftig in meinen Code bekomme... ich hoffe, ich konnte mich klar ausdrücken.

Vielen Dank schon mal für die Hilfe!
Lg Anna
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn du selbst überall die Kontrolle darüber hast, wann etwas ausgegeben wird, dann ist die einfachste Lösung den Text an einen Namen zu binden, und dann kannst du den ausgeben über beliebig viele Kanäle.

Code: Alles auswählen

message = u'file loaded: {}\nMessage: {}'.format(audio_file, response['message'])
print(message)
with open(“Datei”, “a”) as outf:
        outf.write(message)
        outf.write(“\n”) # print macht automatisch ein newline. write nicht.
Und diese 4 Zeilen kannst du am besten in eine Funktion packen, zB log, und die dann immer aufrufen:

Code: Alles auswählen

def log(message):
       print...

log(u'file loaded: {}\nMessage: {}'.format(audio_file, response['message']))
python_newbee
User
Beiträge: 2
Registriert: Freitag 25. Mai 2018, 10:17

Super, danke für die schnelle Antwort.

Ich werde es gleich mal probieren. :)
Antworten