Ich möchte den Druck mit Python in eine TXT-Datei umleiten. Ich habe eine 'for'-Schleife, die die Ausgabe für jede meiner .bam-Dateien' druckt ', während ich ALLE diese Ausgaben in eine Datei umleiten möchte. Also habe ich versucht zu setzen
f = open('output.txt','w'); sys.stdout = f
am Anfang meines Skripts. Allerdings bekomme ich nichts in der .txt-Datei. Mein Skript lautet:
#!/usr/bin/python
import os,sys
import subprocess
import glob
from os import path
f = open('output.txt','w')
sys.stdout = f
path= '/home/xug/nearline/bamfiles'
bamfiles = glob.glob(path + '/*.bam')
for bamfile in bamfiles:
filename = bamfile.split('/')[-1]
print 'Filename:', filename
samtoolsin = subprocess.Popen(["/share/bin/samtools/samtools","view",bamfile],
stdout=subprocess.PIPE,bufsize=1)
linelist= samtoolsin.stdout.readlines()
print 'Readlines finished!'
........print....
........print....
Also, was ist das Problem? Irgendein anderer Weg als dieses sys.stdout?
Ich muss mein Ergebnis so aussehen lassen:
Filename: ERR001268.bam
Readlines finished!
Mean: 233
SD: 10
Interval is: (213, 252)
python
file-writing
LookIntoEast
quelle
quelle
f.write(data)
?f.write(line)
- Am Ende wird ein Zeilenumbruch eingefügt.f.write(line)
den Daten keinen Zeilenumbruch hinzu.f.write(line+'\n')
..Antworten:
Der naheliegendste Weg, dies zu tun, wäre das Drucken in ein Dateiobjekt:
Das Umleiten von stdout funktioniert jedoch auch bei mir. Für ein einmaliges Skript wie dieses ist es wahrscheinlich in Ordnung:
Die externe Umleitung von der Shell selbst ist eine weitere gute Option:
Andere Fragen:
Was ist der erste Dateiname in Ihrem Skript? Ich sehe es nicht initialisiert.
Meine erste Vermutung ist, dass glob keine Bamfiles findet und daher die for-Schleife nicht ausgeführt wird. Überprüfen Sie, ob der Ordner vorhanden ist, und drucken Sie die BAM-Dateien in Ihrem Skript aus.
Verwenden Sie außerdem os.path.join und os.path.basename , um Pfade und Dateinamen zu bearbeiten .
quelle
Sie können den Druck mit dem
>>
Bediener umleiten .In den meisten Fällen ist es besser, einfach normal in die Datei zu schreiben.
oder, wenn Sie mehrere Elemente haben, die Sie mit Leerzeichen dazwischen schreiben möchten, wie z
print
.quelle
sys.stdout
, nicht dass es eine gute Idee war.Da das Dateiobjekt normalerweise eine
write()
Methode enthält , müssen Sie lediglich ein Dateiobjekt an sein Argument übergeben.In Datei schreiben / überschreiben
Schreiben / An Datei anhängen
quelle
sys.stdout
Das funktioniert perfekt:
Jetzt wird das Hallo in die Datei test.txt geschrieben. Stellen Sie sicher, dass Sie das
stdout
mit a schließenclose
. Ohne dieses wird der Inhalt nicht in der Datei gespeichertquelle
sys.stdout.close()
, wenn Sie etwas in die Python-ShellValueError: I/O operation on closed file.
eingeben, wird der Fehler als imgur.com/a/xby9P angezeigt . Der beste Weg, um damit umzugehen, ist zu folgen, was @Gringo Suave gepostet hatNicht benutzen
print
, benutzenlogging
Sie können ändern
sys.stdout
, um auf eine Datei zu verweisen, aber dies ist eine ziemlich umständliche und unflexible Methode, um dieses Problem zu lösen.print
Verwenden Sie daslogging
Modul anstelle von .Mit
logging
können Sie wie gewohnt druckenstdout
oder die Ausgabe in eine Datei schreiben. Sie können sogar die verschiedenen Nachrichtenebene (verwendencritical
,error
,warning
,info
,debug
) auf, beispielsweise nur wichtige Fragen an die Konsole drucken, aber immer noch kleinere Code Aktionen in eine Datei protokollieren.Ein einfaches Beispiel
Importieren
logging
, abrufenlogger
und Verarbeitungsstufe festlegen:Wenn Sie auf stdout drucken möchten:
Wenn Sie auch in eine Datei schreiben möchten (wenn Sie nur in eine Datei schreiben möchten, überspringen Sie den letzten Abschnitt):
Verwenden Sie dann, wo immer Sie sie verwenden würden
print
, eine der folgendenlogger
Methoden:Weitere Informationen zur Verwendung erweiterter
logging
Funktionen finden Sie im hervorragendenlogging
Tutorial in den Python-Dokumenten .quelle
Die einfachste Lösung ist nicht Python; Es ist durch die Schale. Aus der ersten Zeile Ihrer Datei (
#!/usr/bin/python
) geht hervor, dass Sie sich auf einem UNIX-System befinden. Verwendenprint
Sie einfach Anweisungen wie gewohnt und öffnen Sie die Datei in Ihrem Skript überhaupt nicht. Wenn Sie die Datei ausführen, anstattVerwenden Sie zum Ausführen der Datei
wo Sie durch
<filename>
den Namen der Datei ersetzen, in die die Ausgabe gehen soll. Das>
Token weist (die meisten) Shells an, stdout auf die durch das folgende Token beschriebene Datei zu setzen.Eine wichtige Sache, die hier erwähnt werden muss, ist, dass "script.py" ausführbar gemacht werden muss
./script.py
, damit es ausgeführt werden kann.Führen Sie
./script.py
diesen Befehl aus, bevor Sie ihn ausführenchmod a+x script.py
(Machen Sie das Skript für alle Benutzer ausführbar.)quelle
print
an eine Datei weiterleiten. Es ist vernünftig zu erwarten, dass stdout (Stapelspuren und dergleichen) weiterhin auf dem Terminal gedruckt wird.Wenn Sie Linux verwenden, empfehle ich Ihnen, den
tee
Befehl zu verwenden. Die Implementierung sieht folgendermaßen aus:Wenn Sie nichts am Code ändern möchten, ist dies möglicherweise die bestmögliche Lösung. Sie können den Logger auch implementieren, müssen jedoch einige Änderungen am Code vornehmen.
quelle
Diese Antwort mag Ihnen vielleicht nicht gefallen, aber ich denke, es ist die RICHTIGE. Ändern Sie Ihr stdout-Ziel nur, wenn dies unbedingt erforderlich ist (möglicherweise verwenden Sie eine Bibliothek, die nur stdout ausgibt - hier ist dies eindeutig nicht der Fall).
Ich denke, als gute Angewohnheit sollten Sie Ihre Daten im Voraus als Zeichenfolge vorbereiten, dann Ihre Datei öffnen und das Ganze auf einmal schreiben. Dies liegt daran, dass Eingabe- / Ausgabeoperationen umso wahrscheinlicher sind, je länger ein Dateihandle geöffnet ist, wenn bei dieser Datei ein Fehler auftritt (Dateisperrfehler, E / A-Fehler usw.). Nur alles in einem Arbeitsgang zu erledigen, lässt keine Frage offen, wann es schief gegangen sein könnte.
Hier ist ein Beispiel:
Und wenn Sie mit dem Sammeln Ihrer "
'\n'
Datenzeilen " in einer Zeile pro Listenelement fertig sind, können Sie sie mit einigen Zeichen verbinden, um das Ganze als Ausgabetabelle zu erstellen. Vielleicht verpacken Sie Ihre Ausgabeanweisungwith
zur zusätzlichen Sicherheit sogar in einen Block (schließt automatisch Ihr Ausgabehandle, selbst wenn etwas schief geht):Allerdings , wenn Sie eine Menge Daten zu schreiben haben, Sie könnten es ein Stück zu einer Zeit schreiben. Ich denke nicht, dass es für Ihre Anwendung relevant ist, aber hier ist die Alternative:
quelle
Wenn die Umleitung
stdout
für Ihr Problem funktioniert, ist die Antwort von Gringo Suave eine gute Demonstration dafür.Um es noch einfacher zu machen , habe ich eine Version erstellt, die Kontextmanager für eine prägnante verallgemeinerte Aufrufsyntax verwendet, indem ich die folgende
with
Anweisung verwende:Um es zu verwenden, gehen Sie einfach wie folgt vor (abgeleitet von Suaves Beispiel):
Dies ist nützlich, um selektiv umzuleiten,
print
wenn ein Modul es auf eine Weise verwendet, die Sie nicht mögen. Der einzige Nachteil (und dies ist der Dealbreaker für viele Situationen) ist, dass es nicht funktioniert, wenn mehrere Threads mit unterschiedlichen Werten von gewünscht werdenstdout
, dies jedoch eine bessere, allgemeinere Methode erfordert: indirekten Modulzugriff. Sie können Implementierungen davon in anderen Antworten auf diese Frage sehen.quelle
Durch Ändern des Werts von sys.stdout wird das Ziel aller zu druckenden Aufrufe geändert. Wenn Sie das Druckziel auf alternative Weise ändern, erhalten Sie das gleiche Ergebnis.
Ihr Fehler ist woanders:
quelle
Etwas, um die Druckfunktion für Schleifen zu erweitern
quelle
while
und keine Notwendigkeit, die Datei bei der Verwendung zu schließenwith