Chcę przekierować wydruk do pliku .txt przy użyciu języka Python. Mam pętlę „for”, która „wypisze” dane wyjściowe dla każdego z moich plików .bam, podczas gdy chcę przekierować WSZYSTKIE dane wyjściowe do jednego pliku. Więc próbowałem umieścić
f = open('output.txt','w'); sys.stdout = f
na początku mojego scenariusza. Jednak nic nie mam w pliku .txt. Mój skrypt to:
#!/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....
Więc w czym problem? Jakikolwiek inny sposób poza tym sys.stdout?
Chcę, aby mój wynik wyglądał następująco:
Filename: ERR001268.bam
Readlines finished!
Mean: 233
SD: 10
Interval is: (213, 252)
python
file-writing
LookIntoEast
źródło
źródło
f.write(data)
?f.write(line)
- na końcu wstawia znak końca wiersza.f.write(line)
nie dodaje podziału wiersza do danych.f.write(line+'\n')
Jednak zawsze może …Odpowiedzi:
Najbardziej oczywistym sposobem byłoby wydrukowanie do obiektu pliku:
Jednak przekierowanie stdout również działa dla mnie. Prawdopodobnie jest w porządku w przypadku jednorazowego scenariusza, takiego jak ten:
Przekierowanie na zewnątrz z samej powłoki to kolejna dobra opcja:
Inne pytania:
Jaka jest pierwsza nazwa pliku w twoim skrypcie? Nie widzę zainicjowania.
Moje pierwsze przypuszczenie jest takie, że glob nie znajduje żadnych plików bamfiles i dlatego pętla for nie działa. Sprawdź, czy folder istnieje i wydrukuj bamfiles w swoim skrypcie.
Ponadto użyj os.path.join i os.path.basename do manipulowania ścieżkami i nazwami plików.
źródło
Możesz przekierować drukowanie z
>>
operatorem.W większości przypadków lepiej jest po prostu normalnie pisać do pliku.
lub, jeśli masz kilka elementów, które chcesz zapisać ze spacjami, na przykład
print
:źródło
sys.stdout
, a nie to, że był to dobry pomysł.Ponieważ obiekt plikowy zwykle zawiera
write()
metodę, wszystko, co musisz zrobić, to przekazać obiekt plikowy do jego argumentu.Zapisz / nadpisz do pliku
Zapisz / dołącz do pliku
źródło
sys.stdout
:(Działa to doskonale:
Teraz hello zostanie zapisane w pliku test.txt. Upewnij się, że zamykasz
stdout
za pomocąclose
, bez niego zawartość nie zostanie zapisana w plikuźródło
sys.stdout.close()
, jeśli wpiszesz cokolwiek w powłoce Pythona, wyświetli się błąd jakoValueError: I/O operation on closed file.
imgur.com/a/xby9P . Najlepszym sposobem radzenia sobie z tym jest śledzenie tego, co @Gringo Suave opublikowałNie używaj
print
, używajlogging
Możesz zmienić,
sys.stdout
aby wskazywał na plik, ale jest to dość niezgrabny i nieelastyczny sposób rozwiązania tego problemu. Zamiast używaćprint
, użyjlogging
modułu.Za pomocą
logging
możesz drukować tak, jak chceszstdout
, lub możesz również zapisać wynik do pliku. Można nawet korzystać z różnych poziomów wiadomość (critical
,error
,warning
,info
,debug
), na przykład, drukować tylko główne problemy do konsoli, ale nadal zalogować drobne działania kodu do pliku.Prosty przykład
Importuj
logging
, pobierzlogger
i ustaw poziom przetwarzania:Jeśli chcesz drukować na standardowe wyjście:
Jeśli chcesz również pisać do pliku (jeśli chcesz zapisywać tylko do pliku, pomiń ostatnią sekcję):
Następnie, gdziekolwiek byś użył,
print
użyj jednej zlogger
metod:Aby dowiedzieć się więcej o korzystaniu z bardziej zaawansowanych
logging
funkcji, przeczytaj doskonałylogging
samouczek w dokumentacji Pythona .źródło
Najłatwiejszym rozwiązaniem nie jest użycie Pythona; to przez powłokę. Z pierwszego wiersza twojego pliku (
#!/usr/bin/python
) Domyślam się, że pracujesz w systemie UNIX. Po prostu użyjprint
instrukcji tak jak zwykle i nie otwieraj pliku w ogóle w swoim skrypcie. Kiedy idziesz uruchomić plik, zamiastaby uruchomić plik, użyj
gdzie zamieniasz
<filename>
na nazwę pliku, do którego ma trafić wyjście.>
Tokena mówi (większość) muszle Aby ustawić standardowe wyjście do pliku opisanym brzmienie żeton.Jedną ważną rzeczą, o której należy tutaj wspomnieć, jest to, że plik „script.py” musi być uruchamiany, aby
./script.py
mógł działać.Dlatego przed uruchomieniem
./script.py
wykonaj to poleceniechmod a+x script.py
(spraw, aby skrypt był wykonywalny dla wszystkich użytkowników)źródło
print
do pliku. Byłoby rozsądnym oczekiwać, że stdout (ślady stosu i tym podobne) nadal będzie drukowane na terminalu.Jeśli używasz Linuksa, sugeruję użycie
tee
polecenia. Wdrożenie wygląda następująco:Jeśli nie chcesz niczego zmieniać w kodzie, myślę, że może to być najlepsze możliwe rozwiązanie. Możesz również zaimplementować rejestrator, ale musisz wprowadzić pewne zmiany w kodzie.
źródło
Możesz nie lubić tej odpowiedzi, ale myślę, że jest WŁAŚCIWA. Nie zmieniaj miejsca docelowego na stdout, chyba że jest to absolutnie konieczne (być może używasz biblioteki, która wysyła tylko na stdout ???, oczywiście nie w tym przypadku).
Myślę, że dobrym nawykiem jest przygotowanie danych z wyprzedzeniem w postaci ciągu znaków, a następnie otwarcie pliku i zapisanie całości na raz. Dzieje się tak, ponieważ im dłużej masz otwarty uchwyt pliku, tym bardziej prawdopodobne jest wystąpienie błędu w tym pliku (błąd blokady pliku, błąd wejścia / wyjścia itp.). Wykonanie tego wszystkiego w jednej operacji nie pozostawia wątpliwości, kiedy mogło się to udać.
Oto przykład:
A kiedy skończysz zbierać swoje „linie danych”, po jednym wierszu na element listy, możesz połączyć je kilkoma
'\n'
znakami, aby całość stała się tabelą wyjściową; może nawet zawiń swoją instrukcję wyjściową wwith
blok, dla dodatkowego bezpieczeństwa (automatycznie zamknie uchwyt wyjściowy, nawet jeśli coś pójdzie nie tak):Jednak jeśli masz dużo danych, aby napisać, to mógłby napisać to jeden kawałek na raz. Wydaje mi się, że nie ma to znaczenia dla Twojej aplikacji, ale oto alternatywa:
źródło
Jeśli przekierowanie
stdout
działa w Twoim problemie, odpowiedź Gringo Suave jest dobrą demonstracją, jak to zrobić.Aby było jeszcze łatwiej , stworzyłem wersję wykorzystującą menedżery kontekstu do zwięzłej uogólnionej składni wywoływania, używając
with
instrukcji:Aby go użyć, po prostu wykonaj następujące czynności (zaczerpnięte z przykładu Suave'a):
Jest to przydatne do selektywnego przekierowywania,
print
gdy moduł używa go w sposób, którego nie lubisz. Jedyną wadą (i jest to przełamanie transakcji w wielu sytuacjach) jest to, że nie działa, jeśli chce się mieć wiele wątków o różnych wartościachstdout
, ale wymaga to lepszej, bardziej uogólnionej metody: pośredniego dostępu do modułu. Możesz zobaczyć implementacje tego w innych odpowiedziach na to pytanie.źródło
Zmiana wartości sys.stdout powoduje zmianę miejsca docelowego wszystkich wywołań drukowania. Jeśli użyjesz alternatywnego sposobu zmiany miejsca docelowego drukowania, uzyskasz ten sam wynik.
Twój błąd jest gdzie indziej:
źródło
Coś do rozszerzenia funkcji drukowania dla pętli
źródło
while
i nie ma potrzeby zamykania pliku podczas używaniawith