strptime frisst kein Unicode, Workaround gesucht

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
grokenberger
User
Beiträge: 6
Registriert: Freitag 27. Mai 2011, 12:19

Hallo Liste, ich habe hier ein Problem an dem ich Noob mir die Zähne ausbeiße. Vielleicht kann mir ja jemand helfen.

Ich muss Zeitdaten aus einer Datei auswerten. Die Zeiten sehen etwa so aus:
Auftrag beendet am Mittwoch, 22. Februar 2012 um 21:45:40
Das kann ich gut auswerten mit time.strptime, nachdem die locale richtig gesetzt wurde.

Das Problem ist nun, dass die Variable im Unicode daherkommt und time.strptime damit nicht klarkommt:

Code: Alles auswählen

>>> time.strptime("März", "%B")
time.struct_time(tm_year=1900, tm_mon=3, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=60, tm_isdst=-1)
>>> time.strptime(u"März", "%B")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/_strptime.py", line 454, in _strptime_time
    return _strptime(data_string, format)[0]
  File "/usr/lib/python2.7/_strptime.py", line 325, in _strptime
    (data_string, format))
ValueError: time data u'M\xe4rz' does not match format '%B'
Nach meinen Recherchen kann das nur mit einem Workaround umgangen werden, etwa so (von: http://grokbase.com/t/python/python-bug ... -de-locale):
For anyone trying to work around this, unicode date strings
should be encoded to simple Python strings (type of str)
before passing into strptime. Here's an updated version of
the aforementioned test case demonstrating an acceptable
workaround:

Code: Alles auswählen

import locale, time
locale.setlocale(locale.LC_TIME, 'de_DE')
date = u'September'.encode()
format = '%B'
time.strptime(date, format)
Das Problem ist nun, dass das nicht funktioniert wenn der Monat März drankommt, weil da ja ein Umlaut darin vorkommt (was ja das ursprüngliche Problem ist…):

Code: Alles auswählen

>>> import locale, time
>>> locale.setlocale(locale.LC_TIME, '')
'de_DE.UTF-8'
>>> date=u'September'.encode()
>>> date=u'März'.encode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 1: ordinal not in range(128)
Hier komme ich einfach nicht weiter! :K


Kann jemand helfen?

[Edit: bessere Verständlichkeit]
[Edit: noch ein Codebeispiel]
Zuletzt geändert von grokenberger am Freitag 25. Mai 2012, 11:33, insgesamt 1-mal geändert.
BlackJack

@grokenberger: `locale.getlocale()` gibt unter anderem die aktuelle Kodierung zurück. Damit müsstest Du Deine Unicde-Zeichenketten vorher kodieren.
grokenberger
User
Beiträge: 6
Registriert: Freitag 27. Mai 2011, 12:19

Danke, BlackJack, aber wie müsste ich das tun?

Code: Alles auswählen

>>> import locale, time
>>> locale.setlocale(locale.LC_TIME, '')
'de_DE.UTF-8'
>>> locale.getlocale()
(None, None)
Kannst du mir ein Beispiel geben?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Code: Alles auswählen

In [5]: locale.setlocale(locale.LC_TIME, '')
Out[5]: 'en_US.UTF-8'

In [6]: locale.getlocale(locale.LC_TIME)
Out[6]: ('en_US', 'UTF-8')
Du solltest auch `getlocale` nach der Kategorie fragen, die dich interessiert ;)
grokenberger
User
Beiträge: 6
Registriert: Freitag 27. Mai 2011, 12:19

Hallo,

vielen Dank, aber:

Code: Alles auswählen

>>> locale.setlocale(locale.LC_TIME, '')
'de_DE.UTF-8'
>>> locale.setlocale(locale.LC_TIME)
'de_DE.UTF-8'
Wie hilft mir das weiter?
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Um statt in ASCII in das verwendete Encoding zu kodieren:

Code: Alles auswählen

In [1]: import locale

In [2]: import time

In [3]: locale.setlocale(locale.LC_TIME, 'de_DE.UTF-8')
Out[3]: 'de_DE.UTF-8'

In [4]: time.strptime(u'März'.encode(locale.getlocale(locale.LC_TIME)[1]), '%B')
Out[4]: time.struct_time(tm_year=1900, tm_mon=3, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=60, tm_isdst=-1)
BlackJack

@grokenberger: Du sollst nicht zweimal *set*locale aufrufen. Das hilft in der Tat nicht weiter. ;-)
lunar

@grokenberger: ".strptime(u'März'.encode(locale.getpreferredencoding()), '%B')".
grokenberger
User
Beiträge: 6
Registriert: Freitag 27. Mai 2011, 12:19

Super, das funktioniert ja tatsächlich!

Ich verstehe es zwar nicht ganz, bin aber sehr dankbar! ☺
Antworten