Deutsche Umlaute und strptime

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
Benutzeravatar
Cronut
User
Beiträge: 34
Registriert: Sonntag 5. Februar 2017, 09:50
Wohnort: HRO, GER

Guten Tag,
ich bin neu hier und werde hier wohl in Zukunft öfter mal vorbeischauen - so viel vorweg.

Zum eigentlichen Problem, welches mich jetzt eine Weile aufhält, ist diese Exception:

Code: Alles auswählen

ValueError: time data '3. Mär 2012' does not match format '%d. %b %Y'
Ich versuche jetzt schon eine Weile, dieses Datum zu parsen und es will einfach nicht funktionieren:

Code: Alles auswählen

self.dt = datetime.strptime(dt.text, '%d. %b %Y')
(Randnote: dt ist ein Selenium WebElement, daher der Zugriff auf 'text')

Diesen Thread habe ich dazu in diesem Forum gefunden:
viewtopic.php?f=1&t=9904&p=62275&hilit= ... A4r#p62275

Leider ist dies für mich keine Lösung, oder ich müsste alle Monate übersetzen, was ich vermeiden möchte.
Gibt es einen 'modernen' (da der Thread schon alt ist) Weg mit diesem Problem umzugehen?

Mein kleines Program wird auf Windows 10 mit Python 3.0.6 entwickelt und ich verwende:

Code: Alles auswählen

locale.setlocale(locale.LC_ALL, '')
um Locale auf '('de_DE', 'cp1252')' zu setzen (eine Locale de_DE.utf8 existiert bei mir leider nicht, aber würde das das Problem lösen?)

Ich bin noch sehr neu in Python, eventuell kann mir jemand unter die Arme greifen. Wäre sehr dankbar.
Ich könnte mir sonst statt der englischen Bezeichnung noch vorstellen, einfach den Namen durch eine numerische Angabe zu ersetzen. Wie gesagt hoffe ich aber, dass es eventuell einen schöneren Weg gibt.

Danke fürs Lesen und evtl. Antworten,
Cronut
“Clean code always looks like it was written by someone who cares.” (Michael Feathers)
Check out: https://awesome-python.com/
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Versuche doch einfach mal mittels ``strftime`` und Deinem Format-String genau dieses Datum zu erzeugen - wenn dort der März anders kodiert wird, weißt Du definitiv, dass Deine Locale-Einstellungen falsch sind. Dann musst Du nur noch herausfinden, *wie* diese lauten müssen...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
bb1898
User
Beiträge: 199
Registriert: Mittwoch 12. Juli 2006, 14:28

Cronut hat geschrieben: Diesen Thread habe ich dazu in diesem Forum gefunden:
viewtopic.php?f=1&t=9904&p=62275&hilit= ... A4r#p62275

Leider ist dies für mich keine Lösung, oder ich müsste alle Monate übersetzen, was ich vermeiden möchte.
Gibt es einen 'modernen' (da der Thread schon alt ist) Weg mit diesem Problem umzugehen?
"Dies" ist, wenn ich Dich recht verstehe, die Arbeit mit den englischen Monatsbezeichnungen? Im gleichen Thread wird aber auch etwas viel Einfacheres angeboten: "Mrz" statt "Mär". Schlauerweise benutzt das datetime-Modul nämlich diese Abkürzung. Kann man an der Umkehrung sehen:

Code: Alles auswählen

>>> maerztag = datetime.date(2017, 3, 5)
>>> maerztag.strftime("%d. %b %Y")
'05. Mrz 2017'
Die falsche Abkürzung, nicht der Umlaut, ist die Ursache für den Fehler; mit %B statt %b wird "März" richtig interpretiert.

Ich habe Python 3.6 benutzt, aber offensichtlich hat sich da nichts geändert. Im übrigen, so lange Du bei den Kurzbezeichnungen der Monate bleibst, müsstest Du auch für die englische Variante nur vier ändern, nicht alle zwölf (März, Mai, Oktober, Dezember - hab ich einen vergessen?).

Hyperion war schneller als ich. Das kommt davon, wenn man während des Antwortens noch Dinge ausprobiert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich habe das auch mal (mit einem frisch installierten Python 3.6 auf einem Win7 Rechner) ausprobiert:

Code: Alles auswählen

In [15]: iden = date(2017, 3, 15)

In [16]: iden.strftime('%d. %b %Y')
Out[16]: '15. Mar 2017'
LOACLE ist:

Code: Alles auswählen

locale.getdefaultlocale()
('de_DE', 'cp1252')
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
bb1898
User
Beiträge: 199
Registriert: Mittwoch 12. Juli 2006, 14:28

Du hattest aber locale.setlocale(LC_ALL, '') nicht aufgerufen, richtig? Ich hatte es getan, aber versehentlich nicht in den Beitrag geschrieben. Der Vollständigkeit halber die entsprechende Stelle aus der Dokumentation zum locale-Modul:
locale.getdefaultlocale([envvars])
Tries to determine the default locale settings and returns them as a tuple of the form (language code, encoding).

According to POSIX, a program which has not called setlocale(LC_ALL, '') runs using the portable 'C' locale. Calling setlocale(LC_ALL, '') lets it use the default locale as defined by the LANG variable.
Benutzeravatar
Cronut
User
Beiträge: 34
Registriert: Sonntag 5. Februar 2017, 09:50
Wohnort: HRO, GER

Danke erstmal für die bisherigen (umfassenden) Antworten.

Also liegt bei mir einfach eine -nicht kodierungskonforme- Darstellung der Datumsangabe zugrunde. Ärgerlich sowas, dass ich quasi jetzt nur für diesen Fall eine Änderung des Strings vornehmen muss. Habe jetzt auch keine Locale gefunden (gibt es da eine Liste wo ich die Monatsabkürzungen finde?), bei welcher der März als Mär abgekürzt wird. So ist das halt mit fremden Daten (würde Datumangaben immer vollst. numerisch darstellen). :x

Alle anderen Monate funktionieren nämlich einwandfrei. Interessant zu sehen, dass bei @Hyperion bei der gewählten Locale 'Mar' verwendet wird. Da finde ich 'Mrz' weitaus logischer.

Ich hatte an sich halt gehofft, dass das Problem woanders liegt (Kodierung, Locale, o.ä.) und ich den Fall nicht gesonders abfangen muss.
Was wäre denn eine schöne Variante? Würde einfach folgendes benutzen:

Code: Alles auswählen

self.dt = datetime.strptime(dt.text.replace('Mär', 'Mar'), '%d. %b %Y')
Dankend,
Cronut

PS:
@bb1898:
Doch ich habe setlocale aufgerufen, wie im Eingangsbeitrag geschrieben. Wurde dann auf '(de_DE, cp1252)' gesetzt. :)

Edit:
Gerade mal für meine verfügbaren Locales durchlaufen lassen: http://pastebin.com/cgRczJrZ
Anscheinend wird bei jeder deutschen Locale die Abürzung 'Mrz' genutzt und auch sonst nirgendwo 'Mär' (nur märts)
“Clean code always looks like it was written by someone who cares.” (Michael Feathers)
Check out: https://awesome-python.com/
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Man kann die Abkürzungen direkt mit dem locale-Modul abfragen: locale.nl_langinfo(locale.ABMON_3)
»Mrz« scheint die offizielle Abkürzung zu sein. Selbst die Österreicher kürzen Jänner als Jan ab.

Am einfachsten ist es wohl, für dateutil.parser eigene ParseInfos zu schreiben:

Code: Alles auswählen

from dateutil import parser

class GermanParserInfo(parser.parserinfo):
    MONTHS = [
        ('Jan', 'Januar', 'Jänner'),
        ('Feb', 'Februar'),
        ('Mär', 'Mrz', 'März'),
        ('Apr', 'April'),
        ('Mai',),
        ('Jun', 'Juni'),
        ('Jul', 'Juli'),
        ('Aug', 'August'),
        ('Sep', 'Sept', 'September'),
        ('Okt', 'Oktober'),
        ('Nov', 'November'),
        ('Dez', 'Dezember'),
    ]

parser.parse('3. Mär. 2013', GermanParserInfo())
# datetime.datetime(2013, 3, 3, 0, 0)
bb1898
User
Beiträge: 199
Registriert: Mittwoch 12. Juli 2006, 14:28

Cronut hat geschrieben:Interessant zu sehen, dass bei @Hyperion bei der gewählten Locale 'Mar' verwendet wird.
Das liegt daran, dass er setlocale eben nicht aufgerufen hatte und deshalb das "C locale" benutzt wird, bei dem die Sprache englisch oder möglicherweise us-amerikanisch ist. Das wird in dem Dokumentationsbröckchen beschrieben, das ich zitiert hatte.
PS:
@bb1898:
Doch ich habe setlocale aufgerufen, wie im Eingangsbeitrag geschrieben. Wurde dann auf '(de_DE, cp1252)' gesetzt. :)
Du schon, Hyperion nicht, auf ihn bezog sich meine Antwort. Muss man eben doch immer hinschreiben, wenn man kein Zitat für nötig hält.
Benutzeravatar
Cronut
User
Beiträge: 34
Registriert: Sonntag 5. Februar 2017, 09:50
Wohnort: HRO, GER

bb1898 hat geschrieben:Du schon, Hyperion nicht, auf ihn bezog sich meine Antwort.
Huch, Fehler meinerseits. Ja, bei ihm scheint das setlocale zu fehlen. Ein Zitat wäre nicht unbedingt nötig gewesen, aber vllt. eine Nennung. Aber wie gesagt eher Fehler meinerseits, ich nehme immer an, dass sich Beiträge an mich richten, wenn ich der TO bin.

Andererseits erschien mir deine Meldung auch, während ich einen Beitrag senden wollte und damit fehlte der Bezug zu Hyperions Post. Hach ja, die kleinen Hürden des Forenlebens. :lol:
“Clean code always looks like it was written by someone who cares.” (Michael Feathers)
Check out: https://awesome-python.com/
Antworten