Seite 1 von 1

Unicode-Probleme: getfilesystemencoding = ascii statt utf-8

Verfasst: Donnerstag 20. Februar 2014, 15:47
von redeagle
Hi
Ich habe ein kleines Tool geschrieben das ein web-interface haben soll. Dazu lasse ich das Python-Script per Apache laufen.
Das Tool soll zunächst eine Liste mit Verzeichnissen per HTML darstellen. Das läuft soweit auch alles sehr gut. Aber sobald ein Verzeichnis ein unicode-Zeichen (z.B. "ß") im Namen hat bricht alles zusammen :)

Zum auflisten der Verzeichnisse nutze ich os.listdir.
Ausgabe im python-interpreter: "['testa', 'testb', 'scheiße']"
Ausgabe, wenn ich den code im CGI-script nutze: "['testa', 'testb', 'schei\udcc3\udc9fe']"

Offensichtlich verhält sich python in der CGI-Umgebung anders, als wenn ich den Code von der Shell aus ausführe.
Nach etwas Suchen habe ich diverse Funktionen gefunden die mir Codierungs-Settings ausgeben und ändern lassen:

Code: Alles auswählen

    os.environ["LC_ALL"] = "de_DE.UTF-8"

    print(sys.getdefaultencoding())
    print(sys.getfilesystemencoding())
    print(locale.getpreferredencoding())
    print(locale.getdefaultlocale())
Das os.environ-getue ist nötig damit getdefaultlocale nicht (None, None) zurück gibt, und getprefferedencoding nicht ANSI ist

Output im Interpreter: utf-8; utf-8; UTF-8; ('de_DE', 'UTF-8')
In der CGI-Umgebung: utf-8; ascii; UTF-8; ('de_DE', 'UTF-8')

Kurz: In der CGI-Umgebung nutzt Python 3 für das FS-Encodung ASCII statt unicode.


Wie bekomme ich das Problem gelöst? Ist da überhaupt Python das Problem, oder der Server (Apache)? Oder liegt das Problem gar an einer ganz anderen Stelle?

Versionen:
Python: 3.3.2
Apache: 2.4.3
System: Basierend auf Slackware 14

Re: Unicode-Probleme: getfilesystemencoding = ascii statt ut

Verfasst: Donnerstag 20. Februar 2014, 16:02
von BlackJack
Python 3 ist halt doof. :-) Es gibt so etwas wie eine systemweite Dateinamenkodierung unter Linux nicht. Das Konzept welches Python da versucht umzusetzen ist kaputt. Dateinamen sind Byteketten und die dadurch dargestellten Zeichenketten können nicht nur auf verschiedenen Dateisystemen unterschiedlich kodiert sein, sondern auch auf ein und dem selben Dateisystem können ganz unterschiedlich kodierte Dateinamen existieren.

Unter Python 2 würde ich an der Stelle einen Dateinamentyp einführen bei dem die rohen Bytedaten des Namens und eine Darstellung als Unicode getrennt sind.

Re: Unicode-Probleme: getfilesystemencoding = ascii statt ut

Verfasst: Donnerstag 20. Februar 2014, 16:23
von redeagle
Naja, aber os.listdir gibt mir ja bereits "kaputte" Daten. Ich müsste dann den Rückgabe-wert parsen und "\udcc3\udc9f" in die Bytes 0xC0, 0x9F Zerlegen.
Das ist mir zu weit weg von einer schönen Lösung :) - Da macht es fast schon Sinn den Teil des Python-Codes der mit dem Dateisystem in Kontakt kommt in C zu implementieren. (Verzeichnisse erstellen und auflisten)

Zur Dateinamen-Kodierung: Ich verwende IMMER utf-8, was nicht utf-8 ist (sondern z.B. ASCII, bekommt man von win-usern ja recht gerne) wird direkt umbenannt oder gelöscht. Ich lege sehr viel wert darauf dass alles utf-8 fähig ist und nutzt da ich recht viel mit unicodes arbeite.
Ich kann im Einsatzbereich des Skripts 100% sicher sein dass alle Dateinamen utf-8 codiert sind. Es wäre für mich also OK Python mit Gewalt dazu zu bringen in diesem Fall utf-8 zu nutzen.

Re: Unicode-Probleme: getfilesystemencoding = ascii statt ut

Verfasst: Donnerstag 20. Februar 2014, 16:37
von BlackJack
@redeagle: Die Dokumentation im `os`-Modul sagt das `getfilesystemencoding()` verwendet wird, und die Dokumentation dort sagt es ist das Ergebnis von der C-Funktion ``nl_langinfo(CODESET)``. Deren ``man``-Page sagt es ist die Locale-Kategorie LC_CTYPE. Und *die* müsste man ja mit `locale.setlocale()` in Python setzen können. :-)

Re: Unicode-Probleme: getfilesystemencoding = ascii statt ut

Verfasst: Donnerstag 20. Februar 2014, 17:18
von redeagle

Code: Alles auswählen

locale.setlocale(locale.LC_CTYPE, ("de_DE", "UTF-8"))
imp.reload(sys)
…ändert leider nichts an getfilesystemencoding.

Allerdings gibt locale.nl_langinfo(locale.CODESET) nun "UTF-8" statt "ANSI" aus.
Ist zumindest schonmal ein bisschen mehr unicode :D

Re: Unicode-Probleme: getfilesystemencoding = ascii statt ut

Verfasst: Donnerstag 20. Februar 2014, 21:18
von Balmung
Du kannst an os.listdir einen Bytestring übergeben und wirst dann als Rückgabewert die Dateinamen ebenfalls als Bytestrings erhalten.
In den Fällen, in denen Dateien nicht einheitlich kodiert sind, was ja vorkommen kann, ist das womöglich die komfortabelste Möglichkeit unter Python3 mit den Dateinamen klarzukommen.

Re: Unicode-Probleme: getfilesystemencoding = ascii statt ut

Verfasst: Freitag 21. Februar 2014, 13:48
von redeagle
Super, danke. So funktioniert es :)

Code: Alles auswählen

    for entry in os.listdir(PROJECTROOT.encode("utf-8")):
        entry = entry.decode("utf-8")