Paras vastaus
Valitettavasti tähän ongelmaan ei ole yksinkertaista yksirivistä vastausta.
Kuvittele, että jono tulee python-ohjelmaan I / O-toiminnon kautta (luetaan päätelaitteesta, tiedostosta tai verkosta), se kiertää ohjelmaa kopioimalla paikasta toiseen, ja lopulta se saa tuotoksen I / O-toiminnon kautta. Jos määrität stricille unicoden missä tahansa vaiheessa, näet pelätyn ascii codec can"t encode...
-virheen. Valitettavasti sen korjaamiseen ei ole muuta tapaa kuin mennä korjaamalla kaikki paikat koodisi kautta.
Harkitse esimerkiksi:
f\_in = open("filein.txt")
line = f\_in.read()
out\_msg = "The input line was: {line}".format(line=line)
f\_out = open("fileout.txt")
Ellet tiedä, mitä koodausta on käytetty tiedostojen tallentamiseen tiedostoon.txt, sinulla on omituista käyttäytymistä ja jotkut line
-kentässä olevat merkit näyttävät roskilta. (Huomaa: voitit ” t saa ascii codec can"t encode...
-virheen, mutta tulokset ovat silti huonot.) Joten sinun on käytettävä jotain sellaista: f\_in = codecs.open("filein.txt", "rb", "utf-8")
ja toivottava epätoivoisesti että joka tallentanut filein.txt-tiedoston, se oli tallentanut sen utf-8: een eikä muuhun UTF-koodaukseen. (Huomaa: utf-8 on ylöspäin yhteensopiva ascii: n kanssa, joten tavallisella ascii: lla tallennettu tiedosto avautuu hienosti utf-8-koodauksella).
Tähän mennessä olet selvästikin ymmärtänyt, ellet avaamalla fileout.txt käyttämällä asianmukaista unicode-koodausta, olet taas joutumassa vaikeuksiin ja saat ascii codec can"t encode...
-virheen (jos out\_msg-tiedosto sisältää unicode-merkkiä). Joten sinun on tehtävä codecs.open("fileout.txt", "wb", "utf-8")
. (Huomaa vielä kerran: utf-8-koodauksen käyttö tavallisten ascii-tiedostojen tallentamiseen ei ole ongelma, koska se on ylöspäin yhteensopiva, joten jos teksti ei sisällä muita kuin ascii-unicode-merkkejä , utf-8-koodattu tiedosto on identtinen tavallisen ascii-tiedoston kanssa.)
Minua kompastti se, että näiden kahden asian tekeminen ei ole tarpeeksi hyvää. Harkitse tätä päivitettyä koodia:
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")
Tämä voi silti antaa sinulle saman pelätyn virheen kolmannella linja. Se on oikein, ongelmana on, että "The input line was: {line}".format(xxx)"
on str
ja jos line
sisältää kaikki unicode-merkit (joilla tarkoitan merkkejä, joita ei voida koodata ascii-muotoon), olet pulassa.
Korjaus tähän on:
out\_msg = u"The input line was: {line}".format(line=line)
(Kyllä, tämä rivi eroaa koodinäytteen rivistä 3. Sinun täytyy vain katsoa huolellisesti.)
Joten sinulla on se. Sinun täytyy käydä läpi koodisi jokaisella rivillä ja etsi paikkoja, joissa unicode on määritetty str: lle (tai lähetetään menetelmälle, joka odottaa str: tä) ja korjaa kohde unicodeksi str: n sijasta.
Unicoden ymmärtäminen python parempi, katsokaa: http://farmdev.com/thoughts/23/what-i-thought-i-knew-about-unicode-in-python-amounted-to-nothing/
Ymmärtääksesi unicodea yleensä (ja haluaisin erittäin suosittele, että teet tämän) lue Joel Spolskyn ehdoton vähimmäismäärä Jokaisen ohjelmistokehittäjän on ehdottomasti, positiivisesti tiedettävä Unicode- ja merkistöjoukot (Ei Anteeksi!) ”: http://www.joelonsoftware.com/articles/Unicode.html
Ja kun olet siitä kiinnostunut, voit yhtä hyvin lukea: Mikä on paras lähde oppia unicoden parhaista käytännöistä pythonissa?
Nopea ”n Dirty Hack: Jos haluat vain tulostaa jonkin verran tulosta likimääräisenä ascii-muodossa, voit tehdä sen:
import unicodedata
line = unicodedata.normalize("NFKD", line).encode("ascii","ignore")
Tämä korvaa kaikki muut kuin ascii-merkit lähimmällä ascii-ekvivalentilla tai vain ohittaa merkin, jos mikään ei ole sopivaa . On tarpeeksi hyvä moniin tarkoituksiin …
Vastaus
Sinun tulisi muuntaa Unicode-merkkijonosi (jotka on tehty merkkeistä, yksikkö erotettu muistin koosta) tavuiksi käyttämällä asianmukaista koodausta. ennen kuin teet mitään I / O: ta sen kanssa.
Oletusarvon mukaan Python yrittää koodata Unicode-merkkijonosi käyttämällä ASCII-koodausta kirjoittaessasi stdout-tiedostoon (ts. print ), mutta tämä koodaus ei voi edustaa kaikkia Unicode-merkkejä, minkä vuoksi saat virheilmoituksen: ”” ascii ”-koodekki ei voi” koodata merkkiä ”. Melko eksplisiittinen.
Sinun tulisi valita oikea koodaus ja koodata Unicode-merkkijonosi tällä tavalla. Esimerkiksi UTF-8 on tehokas koodaus, joka pystyy käsittelemään kaikki Unicode-merkit. Olettaen, että foo on Unicode-merkkijono, voit tehdä (ja pitäisi): tulostaa foo.encode (”utf -8 ”) vain foo -tulostimen sijaan. Varmista vain, että päätelaitteesi tai mikä tahansa muu ymmärtää valitsemasi koodauksen.Jälleen: UTF-8 on kuumin koodaus siellä tällaisissa tilanteissa, luultavasti haluat käyttää sitä, ellei sinulla ole kovin erityisiä tarpeita.