Używam Pythona ftplib
do napisania małego klienta FTP, ale niektóre funkcje w pakiecie nie zwracają danych wyjściowych w postaci ciągu, ale drukują do stdout
. Chcę przekierować stdout
do obiektu, z którego będę mógł odczytać dane wyjściowe.
Wiem, że stdout
można przekierować do dowolnego zwykłego pliku za pomocą:
stdout = open("file", "a")
Ale wolę metodę, która nie wykorzystuje dysku lokalnego.
Szukam czegoś takiego BufferedReader
w Javie, które można wykorzystać do zawijania buforu w strumień.
stdout = open("file", "a")
sam z siebie niczego przekieruje.Odpowiedzi:
źródło
stdout
obiektu, ponieważ jest on zawsze dostępny pod adresemsys.__stdout__
. Zobacz docs.python.org/library/sys.html#sys.__stdout__ .finally:
bloku, więc zostanie ono również ponownie przypisane, jeśli pomiędzy wystąpi wyjątek.try: bkp = sys.stdout ... ... finally: sys.stdout = bkp
W Pythonie 3.4 jest funkcja contextlib.redirect_stdout () :
Oto przykład kodu, który pokazuje, jak zaimplementować go w starszych wersjach Pythona .
źródło
redirect_stderr
najnowszy Python!Aby dodać do powyższej odpowiedzi Neda: możesz użyć tego do przekierowania wyjścia do dowolnego obiektu, który implementuje metodę write (str) .
Można to wykorzystać z dobrym skutkiem do „przechwytywania” wyjścia standardowego w aplikacji GUI.
Oto głupi przykład w PyQt:
źródło
Począwszy od Pythona 2.6, jako zamiennik można użyć dowolnego elementu implementującego
TextIOBase
API z modułu io. To rozwiązanie umożliwia również używaniesys.stdout.buffer.write()
w Pythonie 3 do zapisywania (już) zakodowanych ciągów bajtów na standardowe wyjście (patrz stdout w Pythonie 3 ). UżywanieStringIO
nie zadziałałoby wtedy, ponieważ ani jedno,sys.stdout.encoding
ani drugie niesys.stdout.buffer
byłoby dostępne.Rozwiązanie wykorzystujące TextIOWrapper:
To rozwiązanie działa dla Python 2> = 2.6 i Python 3.
Należy pamiętać, że nasz nowy
sys.stdout.write()
akceptuje tylko ciągi znaków Unicode isys.stdout.buffer.write()
tylko ciągi bajtów. Może tak nie być w przypadku starego kodu, ale często ma to miejsce w przypadku kodu, który jest tworzony w celu uruchomienia w Pythonie 2 i 3 bez zmian, z czego często korzystasys.stdout.buffer
.Możesz zbudować niewielką odmianę, która akceptuje ciągi znaków Unicode i bajtów dla
write()
:Nie musisz ustawiać kodowania bufora sys.stdout.encoding, ale to pomaga, gdy używasz tej metody do testowania / porównywania danych wyjściowych skryptu.
źródło
Ta metoda przywraca plik sys.stdout, nawet jeśli istnieje wyjątek. Pobiera również dane wyjściowe przed wyjątkiem.
Przetestowano w Pythonie 2.7.10 przy użyciu
io.BytesIO()
Przetestowano w Pythonie 3.6.4 przy użyciu
io.StringIO()
Bob, dodany do sprawy, jeśli uważasz, że cokolwiek ze zmodyfikowanego / rozszerzonego eksperymentowania z kodem może stać się interesujące w jakimkolwiek sensie, w przeciwnym razie możesz to usunąć
źródło
Menedżer kontekstu dla python3:
użyj w ten sposób:
źródło
W Pythonie 3.6 nie ma modułów
StringIO
icStringIO
, więc powinieneś użyć ichio.StringIO
zamiast tego, więc powinieneś zrobić to tak, jak pierwsza odpowiedź:źródło
Posługiwać się
pipe()
i napisz do odpowiedniego deskryptora pliku.https://docs.python.org/library/os.html#file-descriptor-operations
źródło
Oto inne podejście do tego.
contextlib.redirect_stdout
zio.StringIO()
jak udokumentowane jest super, ale to wciąż nieco rozwlekły do codziennego użytku. Oto, jak uczynić go jednowierszowym przez podklasęcontextlib.redirect_stdout
:Ponieważ __enter__ zwraca self, masz obiekt menedżera kontekstu dostępny po zakończeniu with block exits. Ponadto, dzięki metodzie __repr__, reprezentacja ciągu obiektu menedżera kontekstu jest w rzeczywistości stdout. Więc teraz masz,
źródło