[Python] Encodings, Mantis naar Trac problemen.

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
Ik ben op het moment bezig met het installeren van een Trac omgeving, en probeer al een halve dag om de bugs uit ons oude systeem (Mantis) over te zetten naat Trac. Hier is een script voor beschikbaar, Mantis2trac, echter hier loop ik tegen een aantal problemen in verband met speciale tekens.

De brondatabase is een MySQL tabel waar alle encodings ingesteld staan op utf8_general_ci. Het script zelf probeert ook alle strings te vertalen naat UTF-8, door middel van value.encode('utf-8') (een Python functie).

Echter, dit geeft telkens een volgende foutmelding:

code:
1
2
3
4
5
6
7
8
9
10
Traceback (most recent call last):
  File "c:\python26\scripts\mantis2trac.py", line 946, in <module>
    main()
  File "c:\python26\scripts\mantis2trac.py", line 943, in main
    convert(MANTIS_DB, MANTIS_HOST, MANTIS_USER, MANTIS_PASSWORD, TRAC_ENV, TRAC_CLE
  File "c:\python26\scripts\mantis2trac.py", line 683, in convert
    trac.addTicket(**ticket)
  File "c:\python26\scripts\mantis2trac.py", line 387, in addTicket
    desc = description.encode('utf-8')
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 10-12: invalid data


Dit komt voor op elke tekst waar een ë of á of iets dergelijks in staat.

Nu dacht ik 'De brontekst is al in UTF 8, dus ik haal gewoon de conversie weg'. Dan geeft hij echter de foutmelding:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
inserting ticket 91 -- "speciale teken &#966; als ? afgedrukt"
Traceback (most recent call last):
  File "c:\python26\scripts\mantis2trac.py", line 946, in <module>
    main()
  File "c:\python26\scripts\mantis2trac.py", line 943, in main
    convert(MANTIS_DB, MANTIS_HOST, MANTIS_USER, MANTIS_PASSWORD, TRAC_ENV, TRAC_CLEAN)
  File "c:\python26\scripts\mantis2trac.py", line 683, in convert
    trac.addTicket(**ticket)
  File "c:\python26\scripts\mantis2trac.py", line 404, in addTicket
    summary, desc, keywords))
  File "build\bdist.win32\egg\trac\db\util.py", line 122, in execute
  File "build\bdist.win32\egg\trac\db\sqlite_backend.py", line 78, in execute
  File "build\bdist.win32\egg\trac\db\sqlite_backend.py", line 56, in execute
  File "build\bdist.win32\egg\trac\db\sqlite_backend.py", line 48, in _rollback_on_error
sqlite3.ProgrammingError: You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (l
ike text_factory = str). It is highly recommended that you instead just switch your application to Unicode strings.


Dit komt voor in de tekst "speciale teken φ als ? afgedrukt". Nu lijkt het mij echter dat 'ergens' de verkeerde encoding gebruikt wordt, aangezien de tekst in de tracker zelf "speciale teken í als ? afgedrukt " luidt (í ipv φ).

Nu heb ik weinig tot geen kennis van Python noch van karakter encodings. Ik heb Google afgestruind, maar er lijkt geen kant-en-klare oplossing voor mijn probleem te zijn, noch een fix voor het script. Ik heb zelf alle encodings nagekeken, en voor zover ik weet wordt er altijd met UTF-8 gewerkt. Ik kan me moeilijk voorstellen dat de MySQL connector ineens gegevens met een andere encoding zou doorgeven, ook aangezien het script al een tijdje in de running is en, volgens mij, regelmatig met succes gebruikt wordt.

Is er iemand die me hiermee verder kan helpen? Hints en/of tips waar ik nog naar kan kijken?

Het alternatief is om handmatig of met een query alle speciale tekens uit de bug tabel te halen, maar hierdoor kan informatie verloren gaan, en het is natuurlijk veel werk (ook aangezien er 3000 bugs in het systeem staan inclusief opmerkingen van de verschillende developers).

Edit: lijkt erop dat deze issue al langer speelt en dat er geen developers zijn die het opgepakt hebben: zie hier. Heb mijn eigen opmerking daar ook bijgezet.

Acties:
  • 0 Henk 'm!

  • ValHallASW
  • Registratie: Februari 2003
  • Niet online
Wat is het type van description? Is dat 'str' (bytestring) of 'unicode' (unicode code points)? Gezien je foutmelding gok ik dat het een bytestring is in latin-1-representatie, maar controleer dat voor de zekerheid even. Daar zit in ieder geval de kern van je probleem.

Verder moet je even het volgende lezen en begrijpen: http://www.joelonsoftware.com/articles/Unicode.html

Enfin, je sqlite backend wil 'unicode' (unicode code points)-strings hebben. Die zijn niet utf-8, of wat dan ook, dat zijn unicode code points (zie verhaal van Spolsky). Je zult dus je originele string om moeten zetten in code points. Hoe dat moet hangt volledig af van je inkomende string, dus je zult moeten controleren welk formaat die heeft. Ik zou niet vertrouwen op wat MySQL zegt in ieder geval: je kunt best latin-1-encoded data in een utf-8-tabel stoppen (of andersom).


Nog even ter verduidelijking van het gedrag van python (2.x, 3.x heeft andere termen):
Je hebt twee stringklassen:
  • str slaat bytes op
  • unicode slaat unicode code points op
Dit betekent dat een str-object een encoding heeft: een bepaalde representatie van code points in bytes - bijvoorbeeld utf-8, latin-1 of ascii.

Python converteert str-objecten impliciet naar unicode-objecten. Dat gebeurt standaard met de ascii-encoding, maar dat is in te stellen.

Om van str naar unicode te gaan gebruik je .decode('encoding'): je decodeert de representatie naar code points

Om van unicode naar str te gaan gebruik je .encode('encoding'): je codeert de code points in een zekere representatie.

Let op de foutmeldingen die je krijgt: als je een UnicodeDecodeError krijgt terwijl je .encode() aanriep, dan is er sprake van een impliciete conversie!


Als laatste toevoeging nog een stel voorbeelden van de problemen die je tegenkomt:
http://bpaste.net/show/5997/ - aangezien GoT niet overweg kan met een И in een codeblok. Nee, je bent niet de enige met dit soort problemen ;)

[ Voor 41% gewijzigd door ValHallASW op 03-05-2010 21:38 ]