Począwszy od Pythona 2.6 można używać niczego realizacji TextIOBase
API z modułu IO zamiennik. To rozwiązanie umożliwia także użycie sys.stdout.buffer.write()
w Pythonie 3 do napisania (już) zakodowanych ciągów bajtów do stdout (patrz stdout in Python 3). Używanie StringIO
nie zadziałałoby wtedy, ponieważ ani sys.stdout.encoding
ani ani ani ani byłyby dostępne.
Roztwór stosując TextIOWrapper:
import sys
from io import TextIOWrapper, BytesIO
# setup the environment
old_stdout = sys.stdout
sys.stdout = TextIOWrapper(BytesIO(), sys.stdout.encoding)
# do something that writes to stdout or stdout.buffer
# get output
sys.stdout.seek(0) # jump to the start
out = sys.stdout.read() # read output
# restore stdout
sys.stdout.close()
sys.stdout = old_stdout
To rozwiązanie działa w Pythonie 2> = 2,6 i Python 3.
Należy pamiętać, że nasze nowe sys.stdout.write()
akceptuje tylko ciągi znaków Unicode i sys.stdout.buffer.write()
akceptuje tylko ciągi bajtów. To może nie być prawda w przypadku starego kodu, ale często ma miejsce w przypadku kodu, który jest zbudowany do uruchamiania w Pythonie 2 i 3 bez wprowadzania zmian, co ponownie często wykorzystuje numer sys.stdout.buffer
.
Można zbudować niewielką zmianę, która akceptuje Unicode i ciągi bajtów dla write()
:
class StdoutBuffer(TextIOWrapper):
def write(self, string):
try:
return super(StdoutBuffer, self).write(string)
except TypeError:
# redirect encoded byte strings directly to buffer
return super(StdoutBuffer, self).buffer.write(string)
Nie trzeba ustawić kodowanie buforowania sys.stdout.encoding, ale to pomaga przy korzystaniu ta metoda testowania/porównywania danych wyjściowych skryptu.
nie sądzę 'stdout = o pióro ("plik", "a") 'samo przekieruje wszystko. – Alexey