Quando scrivo gli script sysadmin in Python, il buffer su sys.stdout che effettua ogni chiamata a print() è fastidioso, perché non lo faccio Voglio aspettare che un buffer venga svuotato e poi ottenere una grande quantità di righe contemporaneamente sullo schermo, invece voglio ottenere linee di output individuali non appena viene generato un nuovo output dallo script. Non voglio nemmeno aspettare le newline, quindi guarda l'output.L'idioma standard di Python per impostare il buffer sys.stdout su zero non funziona con Unicode
Un linguaggio spesso usato per fare questo in Python è
import os
import sys
sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
questo ha funzionato bene per me per molto tempo. Ora ho notato che non funziona con Unicode. Si prega di consultare il seguente script:
#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import os
import sys
print('Original encoding: {}'.format(sys.stdout.encoding))
sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
print('New encoding: {}'.format(sys.stdout.encoding))
text = b'Eisb\xe4r'
print(type(text))
print(text)
text = text.decode('latin-1')
print(type(text))
print(text)
Questo porta alla seguente output:
Original encoding: UTF-8
New encoding: None
<type 'str'>
Eisb▒r
<type 'unicode'>
Traceback (most recent call last):
File "./export_debug.py", line 18, in <module>
print(text)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 4: ordinal not in range(128)
Mi ci sono volute ore per rintracciare il motivo per esso (il mio script originale era molto più lungo di questo script di debug minimo). È la linea
sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
che ho usato per anni quindi non mi aspettavo alcun problema con esso. Basta commentare questa linea e l'uscita corretta dovrebbe essere simile a questo:
Original encoding: UTF-8
New encoding: UTF-8
<type 'str'>
Eisb▒r
<type 'unicode'>
Eisbär
Allora, qual è lo script mento di fare? Per preparare il mio codice Python 2.7 il più vicino possibile a Python 3.x, sto utilizzando sempre
from __future__ import print_function, unicode_literals
che rende pitone utilizzare il nuovo print() - Funzione ma più importante: rende Python negozio tutte le stringhe come Unicode internamente per impostazione predefinita. Ho un sacco di Latin-1/ISO-8859-1 codifica dei dati, ad esempio
text = b'Eisb\xe4r'
di lavorare con essa il modo previsto, ho bisogno di decodificarlo in Unicode prima, questo è quello che
text = text.decode('latin-1')
è per. Poiché la codifica predefinita è UTF-8 sul mio sistema, ogni volta che stampo una stringa, python codifica la stringa Unicode interna in UTF-8. Ma prima deve essere in perfetto Unicode internamente.
Ora che tutto funziona bene in generale, non solo con un buffer di output a byte zero finora. Qualche idea? Ho notato che sys.stdout.encoding non è impostato dopo la linea di buffering zero, ma non so come impostarlo di nuovo. È un attributo di sola lettura e le variabili di ambiente del sistema operativo LC_ALL o LC_CTYPE sembrano essere valutate solo all'inizio dell'interprete python.
Btw .: "Eisbär" è la parola tedesca per "orso polare".
@martineau Bene, anche la proposta sys.stdout = codecs.getwriter ('utf8') (sys.stdout) non funziona. Ho davvero provato e cercato molto. Quindi immagino che le idee senza averle testate non siano di grande aiuto. –
Ho migrato la domanda per te. La prossima volta, basta "flag" per l'attenzione del moderatore e dicci cosa ti serve! :) – slhck
@MartenLehmann: Il fatto che non sia stato testato è il motivo per cui l'ho postato come commento piuttosto come una risposta. – martineau