Sziasztok!
Van egy olyan problémám, hogy a python sok helyről visszadobja a unicode szövegeket, és exceptionnal elszáll, még encode/decode használata esetén is.
Példa:
#!/usr/bin/python
import sys, MySQLdb, posixpath
from xml.dom import minidom
def getMetaData(doc):
dom = minidom.parseString(doc.encode('utf-8'))
metadata = {}
temp = dom.getElementsByTagName("title")
if len(temp) != 0:
metadata['title'] = MySQLdb.escape_string(temp[0].childNodes[0].data)
temp = dom.getElementsByTagName("date")
if len(temp) != 0:
metadata['date'] = MySQLdb.escape_string(temp[0].childNodes[0].data)
return metadata
xmlfile = posixpath.basename(sys.argv[1])
xmldoc = open(xmlfile, 'r').read()
metadata = getMetaData(xmldoc)
A hiba:
Traceback (most recent call last):
File "./tomysql.py", line 26, in ?
metadata = getMetaData(xmldoc)
File "./tomysql.py", line 14, in getMetaData
dom = minidom.parseString(doc.encode('utf-8'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 220: ordinal not in range(128)
Valaki segítsen, és szájbarágósan elmagyarázni, hogy mi a baj és mi a teendő??? mert már nem értem.
Az alábbi hatástalan:
# -*- coding: utf8 -*-
- 3877 megtekintés
Hozzászólások
Nem tudom mi hiba maradt még a kódban, de tegyük fel, hogy tényleg azt az üzit dobja.
A kód egy nagyobb kódból lett kiollózva.
- A hozzászóláshoz be kell jelentkezni
encode()nal a default az az h dob 1 exceptiont. ha ez nem tetszik akkor lehet mast is valasztani, pl weboldalaknal encode('ascii', 'xmlcharrefreplace') tokeletesen elegendo (lenyeg az optional 2. parameteren van)
- A hozzászóláshoz be kell jelentkezni
ascii???? UTF8 a fájl enkódolása amit olvas! szájbarágóssabban lécci.
Amúgy:
Traceback (most recent call last):
File "./tomysql.py", line 26, in ?
metadata = getMetaData(xmldoc)
File "./tomysql.py", line 14, in getMetaData
dom = minidom.parseString(doc.encode('utf-8', 'xmlcharrefreplace'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 220: ordinal not in range(128)
- A hozzászóláshoz be kell jelentkezni
Amikor beolvasod a fájlt, akkor tedd így:
xmldoc = codecs.open(xmlfile, encoding='utf-8').read()
- A hozzászóláshoz be kell jelentkezni
Ugyan tök nem tudok pythonban programozni, de a perles tapasztalatom és a józan ész azt súgja, hogy doc.encode('utf-8') helyett doc.decode('utf-8') kellene. Ugyanis doc a nyers bytesorozat, ebből akarsz Unicode entitásokból álló sztringet csinálni, ez pedig a dekódolás irány, ha a belső Unicode reprezentációból csinálsz valamilyen kódolás (pl. utf-8) szerinti bytesorozatot, az volna az enkódolás.
- A hozzászóláshoz be kell jelentkezni
Kipróbáltam:
Traceback (most recent call last):
File "./tomysql.py", line 26, in ?
metadata = getMetaData(xmldoc)
File "./tomysql.py", line 14, in getMetaData
dom = minidom.parseString(doc.decode('utf-8'))
File "/usr/lib/python2.4/site-packages/_xmlplus/dom/minidom.py", line 1925, in parseString
return expatbuilder.parseString(string)
File "/usr/lib/python2.4/site-packages/_xmlplus/dom/expatbuilder.py", line 942, in parseString
return builder.parseString(string)
File "/usr/lib/python2.4/site-packages/_xmlplus/dom/expatbuilder.py", line 223, in parseString
parser.Parse(string, True)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 220: ordinal not in range(128)
Ebben az a jó, hogy immáron a külső lib-re tudom áttolni a felelősséget, a rossz meg az, hogy ettől nem lettem okosabb.
- A hozzászóláshoz be kell jelentkezni
Próbáld ki simán ezt:
dom = minidom.parseString(doc)
a neten ezt találtam: http://evanjones.ca/python-utf8.html és ez alapján szerintem ez kell. Ugyanis a read függvénnyel byte-okat olvasol be, mivel nem adod meg a kódolást, és a parseString is byte-okra számít, hiszen magából az xml fájlból veszi ki annak kódolását (és fallbackel utf8-ra, ha nem lenne megemlítve).
- A hozzászóláshoz be kell jelentkezni
Jelen esetben megoldhato lenne minidom.parse() fuggvennyel is, de yo lenne tudni hogy hogyan muxik mindez string eseten, mert lesz olyan kod, ami mysql-bol vagy post adatokbol jovo stringgel dolgozik.
Amugy asszem ez van a kodban is.
- A hozzászóláshoz be kell jelentkezni
Python tudás nélkül:
Az xmldoc gondolom egy XML dokumentum.
Az XML dokumentum az sosem nyers byteok sorozata,
hanem KARAKTEREK sorozata. A karakterek valamilyen
kódolással bytesorozattá vannak konvertálva (sorosítva).
Hogy milyen kódolással vannak a karakterek
bytesorozatra konvertálva, az benne szokott lenni
az XML dokumentumban (az elején), és ha nincs megadva,
akkor a default az UTF-8.
Az esetedben a hibaüzenetből az látszik,
hogy a parser ASCII kódolásúnak gondolja a dokumentumot,
és emiatt a 128 feletti byteokat eleve nem tudja
karakternek értelmezni. Azt gondolnád talán,
hogy a 128 alatti byteok mind karakterek,
ez azonban nincs így. Úgy emlékszem, a szabvány szerint
32 alatt csak a CR, LF, TAB számítanak karakternek.
(Igen, szabvány foglalkozik azzal, hogy mi a karakter.)
Ugyanezért nem igaz, hogy Latin-1 (ISO-8859-1, nyolc bites)
kódolással minden byte egy karakter volna.
Az XML elemzők hibát dobnak, ha a bytesorozat
nem értelmezhető karakterként.
Tehát szerintem az a megoldás, hogy ellenőrizni kell,
hogy az xmldoc tényleg egy szabványos XML dokumentum
legyen, jó legyen benne a kódolás, és jól benne legyen,
hogy milyen kódolású. Azaz a változó tartalma okozza a hibát.
--
CCC3
- A hozzászóláshoz be kell jelentkezni
Az XML teljesen szabvanyos xml, elejen az encoding utf-8 es a doksi telleg utf8 kodolasu. xmllint nem dob ra hibat.
Tisztaban vagyok a xml dokumentumok elmleti felepitesevel, de nekem jelenleg a xml dokumentum mint byte-ok sorozata all rendelkezesemre (tekintve hogy a python keptelen maskent tekinteni a szovegre, ezzel nem tudok mit csinalni).
Mivel ezt a doksit en allitottam elo, ezert teljesen biztos vagyok benne hogyszabvanyos. Bizonyos technikai korlatok megakadalyoznak az xml bepasztazasaban, ezert elnezest kell kerjek, es el kellhidd latatlanba.
Ha egy teljesen szabvanyos angol nyelvu doksit adok neki, semmi gond. Mindig csak a utf karakterek jelentenek problemat.
- A hozzászóláshoz be kell jelentkezni
nekem jelenleg a xml dokumentum mint byte-ok sorozata all rendelkezesemre
Persze, végül is minden byteok sorozata. Hogy az XML karakterekből áll, azt úgy kell érteni, hogy karakterek vannak benne valamilyen kódolással bytesorozatra konvertálva (nem pedig összevissza byteok).
Lehet, hogy jó az XML dokumentum, de a parser mégis azt hiszi, hogy ASCII kódolású. Ebből gondolom:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 220: ordinal not in range(128)
Ha az XML 'ascii' kódolású, akkor a 0xc3 az egy 'összevissza' byte.
--
CCC3
- A hozzászóláshoz be kell jelentkezni
Még egy dolog. Amikor Latin-1 kódolású XML-t elemeztem Python minidom-mal, akkor a site.py-ban a def setencoding()-ban a default kódolást átállítottam 'latin-1'-re, másként az ékezetes betűkön kiakadt. UTF-8-cal nem próbáltam a Pythont, de ennek mintájára próbáld átírni a kódolást a site.py-ban 'UTF-8'-ra.
Ez persze zavaros, hiszen az elemzőnek ahhoz a kódoláshoz kellene alkalmazkodni, ami magában az XML dokumentumban van megadva, függetlenül a programod kódolásától, vagy a hoston beállított kódolástól. Ha ez nem így van, az Python hibája. Azt gondoltam, ezen már túl vannak.
--
CCC3
- A hozzászóláshoz be kell jelentkezni
Ezt meg fogom probalni. Bar a forras deklaralja a coding:utf8 direktivat, egyetlen ekezetes betu sincs benne, ergo lehet hogy a python hulye.
- A hozzászóláshoz be kell jelentkezni
A forrásban lévő utf-8 direktívának ehhez semmi köze. Az arra szolgál, hogy a forrásban leírt sztring (pl. x='éáű') esetén az értelmező tudja, hogy az milyen kódolású.
- A hozzászóláshoz be kell jelentkezni
Már tegnap este válaszoltam, biztos nem vetted észre. Szóval amikor beolvasod a fájlt (a forrásod végén, az utolsó előtti sor), akkor tedd így:
xmldoc = codecs.open(xmlfile, encoding='utf-8').read()
Kipróbáltam, így szépen lefutott a kódod.
================================================
[szerk] Hahó Trey, 10:24 van. Valami időzóna tréfa lehet.
- A hozzászóláshoz be kell jelentkezni
Megnezem, igerem. Most eppen reinstall alatt van a gepem, de amint lesz hasznalhato rendszer azonnal megnezem, becsszo.
- A hozzászóláshoz be kell jelentkezni
godri, én most elhiszem hogy hülye vagyok.
~ $ ./tomysql mynews.xml
Traceback (most recent call last):
File "./hirek/tomysql.py", line 27, in ?
metadata = getMetaData(xmldoc)
File "./hirek/tomysql.py", line 15, in getMetaData
dom = minidom.parseString(doc)
File "/usr/lib/python2.4/xml/dom/minidom.py", line 1925, in parseString
return expatbuilder.parseString(string)
File "/usr/lib/python2.4/xml/dom/expatbuilder.py", line 940, in parseString
return builder.parseString(string)
File "/usr/lib/python2.4/xml/dom/expatbuilder.py", line 223, in parseString
parser.Parse(string, True)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe1' in position 139: ordinal not in range(128)
tomysql.py
#!/usr/bin/python
import sys, MySQLdb, posixpath
import codecs
from xml.dom import minidom
def connect():
try:
conn = MySQLdb.connect("localhost", "root", "ut9uUb7", "gentoosite")
return conn.cursor()
except MySQLdb.OperationalError, msg:
print msg
def getMetaData(doc):
dom = minidom.parseString(doc)
metadata = {}
temp = dom.getElementsByTagName("title")
if len(temp) != 0:
metadata['title'] = MySQLdb.escape_string(temp[0].childNodes[0].data)
temp = dom.getElementsByTagName("date")
if len(temp) != 0:
metadata['date'] = MySQLdb.escape_string(temp[0].childNodes[0].data)
return metadata
xmlfile = posixpath.basename(sys.argv[1])
xmldoc = codecs.open(xmlfile, 'r', encoding='utf-8').read()
metadata = getMetaData(xmldoc)
mynews.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE news SYSTEM "/dtd/guide.dtd">
<news category="gentoo" link="mynews.xml">
<poster>Garami Gábor</poster>
<date>2007-04-06</date>
<title>Ez egy tesz hír</title>
<summary>Elloptak egy hidat az M3 bevezető szakaszánál. A tettesek még szabadlábon</summary>
<body>
<p>
<!-- Ez egy nagyon érdekes hír... :) -->
Tegnapról ma hajnalra virradólag elloptak egy felüljárót az <c>M3</c> bevezető szakaszánál. Az ellopás
tényét egy névtelen telefonáló jelentette be, miután nem tudott továbbhajtani az úton.
A híd értéke körülbelül 4 000 000 Ft, ám az újraépítése ennél sokkal többe fog kerülni, mivel fel
kell bontani a híd visszavezető szakaszát. A tettesek alaposan gyanusíthatók a győri
<uri link="/news/szoborlopas.xml">Sántha Ferenc</uri> szobor ellopásával is.
</p>
</body>
</news>
PS: Természetesen a hír koholmány, a valósághoz semmi köze.
- A hozzászóláshoz be kell jelentkezni
Viszont egy erős hax eredményeképp megy:
import sys, MySQLdb, posixpath
import codecs
from xml.dom import minidom
reload(sys)
sys.setdefaultencoding('utf-8')
def connect():
try:
conn = MySQLdb.connect("localhost", "root", "ut9uUb7", "gentoosite")
return conn.cursor()
except MySQLdb.OperationalError, msg:
print msg
def getMetaData(doc):
dom = minidom.parseString(doc)
metadata = {}
temp = dom.getElementsByTagName("title")
if len(temp) != 0:
metadata['title'] = MySQLdb.escape_string(temp[0].childNodes[0].data)
temp = dom.getElementsByTagName("date")
if len(temp) != 0:
metadata['date'] = MySQLdb.escape_string(temp[0].childNodes[0].data)
return metadata
xmlfile = posixpath.basename(sys.argv[1])
# xmldoc = codecs.open(xmlfile, 'rb', encoding='utf-8').read()
xmldoc = open(xmlfile, 'rb').read()
metadata = getMetaData(xmldoc)
Végül is mrev hatására találtam meg még telepítés alatt azt az oldalt, ahol elmagyarázzák, hogy a fenti hack (gyk: reload(sys) sys.setdefaultencoding('utf-8') ) miért nem ajánlott. Ha valamit nem ajánlanak, az általában működni szokott, csak vagy csúgya vagy secu hack. Namost ezek közül mindkettő hidegen hagy jelen esetben.
PS: ami tuti nem jó, arra általában azt mondják hogy tilos.
- A hozzászóláshoz be kell jelentkezni
Helyesen:
import sys, MySQLdb, posixpath from xml.dom import minidom def getMetaData(doc): dom = minidom.parseString(doc) metadata = {} temp = dom.getElementsByTagName("title") if len(temp) != 0: metadata['title'] = MySQLdb.escape_string(temp[0].childNodes[0].data.encode('utf-8')) temp = dom.getElementsByTagName("date") if len(temp) != 0: metadata['date'] = MySQLdb.escape_string(temp[0].childNodes[0].data.encode('utf-8')) return metadata xmlfile = posixpath.basename(sys.argv[1]) xmldoc = open(xmlfile, 'r').read() metadata = getMetaData(xmldoc) print metadata['title']
- A hozzászóláshoz be kell jelentkezni
Ne haragudj, de ezt most nem értem. Persze, ez lenne a helyes - ha a python képes lenne menet közben kódolást váltani.
Mivel azonban (nálam) nem képes, az import sor után mindenképp kell a reload(sys): setdefaultencoding('utf-8').
Értsétek meg, én már kipróbáltam azt hogy a stringeken nyomok .encode('utf-8') függvényt, de folyamatosan a fenti üzenetet kapom (UnicodeError: The 'ascii' encoder can't ...).
Tényleg nem nézek senkit se hülyének, ha valaki nagyon nem hiszi, kérjen tőlem ssh jogot, adok, belép, megmutatom. Higgyétek el, hogy bármily szép megoldás lenne ez, nálam NEM MŰKÖDIK.
Vagy a MySQLdb.escapestring vagy az xml-feldolgozó rész hal meg.
- A hozzászóláshoz be kell jelentkezni
Ki is próbáltad _ezt_ a kódot? Mert én igen, és működött. (python 2.4.3, mysql-python 1.2.1, pyxml 0.8.4) Esetleg más verziójú mysql-python lehet gond.
- A hozzászóláshoz be kell jelentkezni
AAARRGGGH... miért nincs jogom szerkeszteni ezt?????
Ilyen rövidke szöveggel megy. Próbálok valahonnan máshonnan új kommentet nyitni.
trey, infót kérek: van méretkorlát a kommenteken???
Válasz (txt-ben :@) Itt
- A hozzászóláshoz be kell jelentkezni
Fel tudnád tenni a _teljes_ programot és xml-t valahova, hogy megnézhessük?
- A hozzászóláshoz be kell jelentkezni
- A hozzászóláshoz be kell jelentkezni
xmldoc = MySQLdb.escape_string(xmldoc.encode('utf-8'))
helyett elég
xmldoc = MySQLdb.escape_string(xmldoc)
- A hozzászóláshoz be kell jelentkezni
Traceback (most recent call last):
File "./tomysql_hup.py", line 50, in ?
conn.execute(sql % (xmldoc, xmlfile, metadata['title'], metadata['date']))
File "/usr/lib/python2.4/site-packages/MySQLdb/cursors.py", line 146, in execute
query = query.encode(charset)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 220: ordinal not in range(128)
- A hozzászóláshoz be kell jelentkezni
Nem akarlak megbántani, de most tényleg azt várod, hogy sorról-sorra javítsuk ki a programodat? Esetleg utána kellene olvasnod kicsit a témának. Modjuk kezdd ezzel:
http://diveintopython.org/xml_processing/unicode.html
- A hozzászóláshoz be kell jelentkezni
Nézd, én nem várok el semmit. Van egy megoldás ami nekem müködik (reload (sys); sys.setdefaultencoding('utf-8');). Te elkezdted, hogy ez emígy is működhet. Én azért szálltam bele ebbe a szálba mert kiváncsi voltam, hogy akkor ezt így most hogy.
Ne hidd, hogy nem gugliztam (spec amit adtál oldalt azt még nem láttam, átolvasom, köszönöm), csak már rém untam, hogy minden, a gugli által kidobott módszer a fenti hibaüzit eredményezte.
Sajnálom hogy rabooltam az idődet, és köszönöm a segítségedet.
- A hozzászóláshoz be kell jelentkezni
Nem raboltad az időmet, csupán arra gondoltam, hogy nagyobb hasznodra lehet a jövöben, ha tényleg megérted a dolgokat, és nem csak "vakon" lövöldözöl.
- A hozzászóláshoz be kell jelentkezni
Átolvastam a linket, és jobbára ők is a setdefaultencoding módszert ajánlják ahogy elnéztem.
Igen, próbálom megérteni, de jelenleg még elég illogikusnak tűnik a dolog, hogy mi miért működik úgy, ahogy; és miért nem. Na mindegy.
- A hozzászóláshoz be kell jelentkezni