Hoe UTF-8-gecodeerde tekst naar de console in Python < 3?

Ik gebruik een recent Linux-systeem waarbij al mijn landinstellingen UTF-8 zijn:

LANG=de_DE.UTF-8
LANGUAGE=
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC="de_DE.UTF-8"
LC_TIME="de_DE.UTF-8"
...
LC_IDENTIFICATION="de_DE.UTF-8"
LC_ALL=

Nu wil ik UTF-8-gecodeerde inhoud naar de console schrijven.

Op dit moment gebruikt Python UTF-8 voor de FS-codering, maar houdt het bij ASCII voor de standaardcodering 🙁

>>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> sys.getfilesystemencoding()
'UTF-8'

Ik dacht dat de beste (schone) manier om dit te doen het instellen van de omgevingsvariabele PYTHONIOENCODINGwas. Maar het lijkt erop dat Python het negeert. Op mijn systeem krijg ik tenminste steeds asciials standaardcodering, zelfs na het instellen van de envvar.

# tried this in ~/.bashrc and ~/.profile (also sourced them)
# and on the commandline before running python
export PYTHONIOENCODING=UTF-8

Als ik het volgende doe aan het begin van een script, werkt het wel:

>>> import sys
>>> reload(sys)  # to enable `setdefaultencoding` again
<module 'sys' (built-in)>
>>> sys.setdefaultencoding("UTF-8")
>>> sys.getdefaultencoding()
'UTF-8'

Maar die benadering lijkt onrein. Dus, wat is een goede manier om dit te bereiken?

Tussenoplossing

In plaats van de standaardcodering te wijzigen – wat geen goed ideeis (zie het antwoord van mesilliac) – omwikkel ik gewoon sys.stdoutmet een StreamWriterals volgt:

sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout)

Zie deze kernvoor een kleine hulpprogramma-functie die het afhandelt.


Antwoord 1, autoriteit 100%

Het lijkt erop dat dit niet wordt aanbevolen.

Fedora stelde voor de systeemlandinstelling als standaard te gebruiken,
maar blijkbaar breekt dit andere dingen.

Hier is een citaat uit de mailinglijstdiscussie:

De enige ondersteunde standaardcoderingen in Python zijn:
 Python 2.x: ASCII
 Python 3.x: UTF-8
Als je deze verandert, sta je er alleen voor en zullen er vreemde dingen gebeuren
beginnen te gebeuren. De standaardcodering heeft niet alleen invloed op:
de vertaling tussen Python en de buitenwereld, maar ook
alle interne conversies tussen 8-bit strings en Unicode.
Hacks zoals wat er gebeurt in de pango-module (instellen van de
standaardcodering naar 'utf-8' door de sitemodule opnieuw te laden in
om de sys.setdefaultencoding() API terug te krijgen) zijn gewoon
ronduit verkeerd en zal ernstige problemen veroorzaken sinds Unicode
objecten cachen hun standaard gecodeerde weergave.
Schakel het gebruik van een op landinstellingen gebaseerde standaardcodering niet in.
Als je alleen maar de coderingen wilt krijgen van
stdout en stdin correct zijn ingesteld voor leidingen, zou u moeten doen
verander in plaats daarvan het .encoding-kenmerk van die (alleen).
--
Marc-André Lemburg
eGenix.com

Antwoord 2, autoriteit 83%

Dit is hoe ik het doe:

#!/usr/bin/python2.7 -S
import sys
sys.setdefaultencoding("utf-8")
import site

Let op de -Sin de bangline. Dat vertelt Python de module siteniet automatisch te importeren. De module siteis wat de standaardcodering instelt en de methode verwijdert, zodat deze niet opnieuw kan worden ingesteld. Maar zal eren wat al is ingesteld.


Antwoord 3, autoriteit 34%

Hoe UTF-8-gecodeerde tekst naar de console in Python < 3?

print u"some unicode text \N{EURO SIGN}"
print b"some utf-8 encoded bytestring \xe2\x82\xac".decode('utf-8')

d.w.z. als u een Unicode-tekenreeks heeft, drukt u deze rechtstreeks af. Als je hebt
een bytestring en converteer deze dan eerst naar Unicode.

Uw landinstellingen (LANG, LC_CTYPE) geven een utf-8 landinstelling aan en
daarom zou je (in theorie) een utf-8 bytestring rechtstreeks kunnen afdrukken en het
moet correct worden weergegeven in uw terminal (als terminalinstellingen)
consistent zijn met de landinstellingen en dat zouden ze ook moeten zijn), maar jij
zou het moeten vermijden: de karaktercodering van uw . niet hardcoderen
omgeving in uw script
; in plaats daarvan Unicode rechtstreeks afdrukken.

Er zijn veel verkeerde aannames in uw vraag.

U hoeft PYTHONIOENCODINGniet in te stellen met uw landinstellingen,
om Unicode naar de terminal af te drukken. utf-8 locale ondersteunt alle Unicode-tekens, d.w.z. het werkt zoals het is.

U hebt de tijdelijke oplossing sys.stdout =
codecs.getwriter(locale.getpreferredencoding())(sys.stdout)
. Het kan
breken als een code (die u niet beheert) bytes moet afdrukken
en/of het kan breken terwijl
Unicode afdrukken naar Windows-console (verkeerde codepagina, kan niet-decodeerbare tekens afdrukken). Correcte landinstellingen en/of PYTHONIOENCODINGenvvar zijn voldoende. Als u sys.stdoutmoet vervangen, dan gebruik io.TextIOWrapper()in plaats van codecsmodulezoals win-unicode-consolepakketdoet.

sys.getdefaultencoding()is niet gerelateerd aan uw landinstellingen en aan
PYTHONIOENCODING. Uw veronderstelling dat het instellen van PYTHONIOENCODING
moet veranderen sys.getdefaultencoding()is onjuist. Je zou moeten
controleer in plaats daarvan sys.stdout.encoding.

sys.getdefaultencoding()wordt niet gebruikt wanneer u afdrukt naar de
troosten. Het kan worden gebruikt als een fallback op Python 2 als stdout is
omgeleid naar een bestand/pipe tenzij PYTHOHIOENCODINGis ingesteld:

$ python2 -c'import sys; print(sys.stdout.encoding)'
UTF-8
$ python2 -c'import sys; print(sys.stdout.encoding)' | cat
None
$ PYTHONIOENCODING=utf8 python2 -c'import sys; print(sys.stdout.encoding)' | cat
utf8

Bel sys.setdefaultencoding("UTF-8")niet aan; het kan je beschadigen
gegevens stilen/of breken modules van derden die niet verwachten
het. Onthoud dat sys.getdefaultencoding()wordt gebruikt om bytestringen te converteren
(str) van/naar unicodein Python 2 implicietbijv. "a" + u"b". Zie ook,
het citaat in het antwoord van @mesilliac.


Antwoord 4, autoriteit 17%

Als het programma niet de juiste tekens op het scherm weergeeft,
d.w.z. ongeldig symbool,
voer het programma uit met de volgende opdrachtregel:

PYTHONIOENCODING=utf8 python3 yourprogram.py

Of het volgende, als uw programma een wereldwijd geïnstalleerde module is:

PYTHONIOENCODING=utf8 yourprogram

Op sommige platforms zoals Cygwin (mintty.exeterminal) met Anaconda Python(of Python 3), voer je gewoon export PYTHONIOENCODING=utf8en
later uitvoeren werkt het programma niet,
en je moet altijd elke keer PYTHONIOENCODING=utf8 yourprogramdoen om het programma correct uit te voeren.

In Linux, in het geval van sudo, kun je proberen het argument -Edoor te geven om de gebruikersvariabelen naar het sudo-proces te exporteren:

export PYTHONIOENCODING=utf8
sudo -E python yourprogram.py

Als je dit probeert en het heeft niet gewerkt, moet je een sudo-shell invoeren:

sudo /bin/bash
PYTHONIOENCODING=utf8 yourprogram

Gerelateerd:

  1. Afdrukken UTF-8-gecodeerde tekst naar de console in Python < 3?
  2. Standaardcodering van Python wijzigen?
  3. UTF-8 forceren via cp1252 (Python3)
  4. Python-pad permanent instellen voor Anaconda binnen Cygwin
  5. https://superuser.com/questions/1374339/what -doet-de-e-in-sudo-e-do
  6. Waarom bash -c ‘var= 5 printf “$var”‘ drukt geen 5 af?
  7. https://unix.stackexchange.com/questions/296838 /wat-het-verschil-tussen-eval-en-exec

Antwoord 5, autoriteit 10%

Terwijl we ons realiseren dat de OP-vraag voor Linux is: als je hier via een zoekmachine terechtkomt, lost het volgende het probleem op in Windows 10:

set PYTHONIOENCODING=utf8
python myscript.py

Other episodes