Hvordan komme deg rundt Python-feilen ' UnicodeEncodeError: ' ascii ' kodeken kan ikke kode tegn … ' når du bruker et Python-skript på kommandolinjen


Beste svaret

Beklager, det er ikke noe enkelt svar på en linje på dette problemet.

Tenk deg at en streng kommer inn i et pythonprogram via en I / O-operasjon (lest fra terminal, eller fra fil eller fra nettverket), den gjør veien rundt programmet og blir kopiert fra sted til sted, og til slutt får den utgang via en I / O-operasjon. Når du tilordner en unicode til en str, vil du se den fryktede ascii codec can"t encode... feilen. Dessverre er det ingen enkel måte å fikse det annet enn å gå gjennom koden din for å fikse alle flekkene.

Tenk for eksempel på:

f\_in = open("filein.txt")

line = f\_in.read()

out\_msg = "The input line was: {line}".format(line=line)

f\_out = open("fileout.txt")

Med mindre du vet hvilken koding som ble brukt når du lagret filein.txt, ser du litt bisarr oppførsel, og noen tegn i line vil se ut som søppel. (Merk: du vant » t får feilen ascii codec can"t encode..., men resultatene vil være dårlige.) Så du må bruke noe sånt som: f\_in = codecs.open("filein.txt", "rb", "utf-8") og så håpe desperat at den som lagret filein.txt hadde lagret den i utf-8 og ikke en av de andre UTF-kodingene. (Merk: utf-8 er kompatibelt med ascii oppover, så en fil som ble lagret ved bruk av vanlig ascii vil åpne bra ved hjelp av utf-8-koding).

Nå har du selvsagt innsett at med mindre du åpne fileout.txt ved å bruke en passende unicode-koding, vil du igjen få problemer og få ascii codec can"t encode... feilen (hvis out\_msg inneholder noe unicode-tegn). Så du må gjøre codecs.open("fileout.txt", "wb", "utf-8"). (Merk igjen: bruk av en utf-8-koding for å lagre vanlig ascii er ikke et problem, siden den er kompatibel oppover, så hvis teksten ikke inneholder unicode-tegn som ikke er ascii , den utf-8-kodede filen er identisk med en vanlig ascii-fil.)

Det som løste meg opp var at det å gjøre disse to tingene ikke er bra nok. Vurder denne oppdaterte koden:

f\_in = codecs.open("filein.txt", "rb", "utf-8")

line = f\_in.read()

out\_msg = "The input line was: {line}".format(line=line)

f\_out = codecs.open("fileout.txt", "wb", "utf-8")

Dette kan fremdeles gi deg den samme fryktede feilen på den tredje linje. Det er riktig, problemet er at "The input line was: {line}".format(xxx)" er en str og hvis line inneholder eventuelle unicode-tegn (som jeg mener tegn som ikke kan kodes til ascii) du er i trøbbel.

Løsningen på det er:

out\_msg = u"The input line was: {line}".format(line=line)

(Ja, denne linjen er forskjellig fra linje 3 i kodeeksemplet. Du må bare se nøye.)

Så der har du det. Trenger å gå gjennom hver linje i koden din og finn steder der unicode tildeles str (eller sendes til en metode som forventer en str) og fikser destinasjonen som unicode i stedet for str.

For å forstå unicode i python bedre, ta en titt på: http://farmdev.com/thoughts/23/what-i-thought-i-knew-about-unicode-in-python-amounted-to-nothing/

For å forstå unicode generelt (og jeg ville høyt anbefaler at du gjør dette) les Joel Spolsky «s» The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Unnskyldninger!) «: http://www.joelonsoftware.com/articles/Unicode.html

Og mens du handler om det, kan du like godt lese: Hva er den beste kilden for å lære om unicode beste praksis i python?

Rask «n Skitten hack: Hvis du bare vil få utskrifter skrevet med omtrentlig ascii, kan du gjøre:

import unicodedata

line = unicodedata.normalize("NFKD", line).encode("ascii","ignore")

Dette vil erstatte alle ikke-ascii-tegn med det nærmeste ascii-ekvivalenten, eller bare ignorere tegnet hvis ingenting er passende . Er god nok til mange formål …

Svar

Du bør konvertere Unicode-strengene dine (som er laget av tegn, en enhet frakoblet fra minnestørrelse) til byte ved å bruke riktig koding før du gjør noen I / O med den.

Som standard prøver Python å kode Unicode-strengen din ved hjelp av ASCII-kodingen når du skriver til stdout (dvs. bruker utskrift ), men denne kodingen kan ikke representere alle Unicode-tegn, og det er grunnen til at du får den feilen: «» ascii «-kodek kan ikke kode kode». Ganske eksplisitt.

Du bør velge en riktig koding, og kode Unicode-strengen ved hjelp av den. For eksempel er UTF-8 en effektiv koding som kan håndtere alle Unicode-tegn. Forutsatt at foo er en Unicode-streng, kan du (og bør) gjøre: skrive ut foo.encode («utf -8 «) i stedet for bare print foo . Bare sørg for at terminalen din eller hva som helst forstår kodingen du velger.Igjen: UTF-8 er den hotteste kodingen der ute for slike scenarier, du vil sannsynligvis ønske å bruke den med mindre du har veldig spesifikke behov.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *