Ich möchte in PyDown [1] endlich das Problem lösen, das Sonderzeichen in Datei/Verz.-Namen richtig in der erzeugen Webseite angezeigt werden. Das ist allerdings nicht ganz so einfach, wie mir scheint :( Eine interessante Seite zum Thema ist [2]. Unter dem Punkt "File system" hab ich ein paar Anregungen und auch work-a-rounds gefunden. Der Königsweg ist es wohl, intern alles in unicode zu handhaben und am Ende wird es dann durch die jinja Template engine [3] nach UTF-8 gewandelt. Allerdings ist das wohl nicht so einfach :( Eigentlich sollte os.unlink(u"path") alle Verz. Einträge als unicode zurück liefern. Das tut es allerdings nicht wirklich. Unter Windows geht's unter Linux gibt's Probleme, da Einträge mit Sonderzeichen bei mir kein Unicode sind :( Ich möchte nicht ausschließen, das es evtl. an meiner Ubuntu-Version liegt, die evtl. falsch eingestellt ist. Wobei ich nicht weiß wie ich das ändern könnte. Auf jeden Fall hab ich mir ein Test-Skript geschrieben, welches mehr Aufschlüsse geben soll [4] Doch selbst wenn man alle Verz.-Einträge als unicode hat, gibt es Probleme mit einigen Python "Befehlen"... Denn nicht alle mögen Unverständnisserweise unicode. z.B. os.path.* Leider spuck die Doku in dem Zusammenhang nicht viel aus :( Also was kann man tun??? Offensichtlich gibt es auch noch einige Bugs: http://sourceforge.net/tracker/index.php?func=detail&aid=767645&group_id=5470&atid=105470 http://sourceforge.net/tracker/index.php?func=detail&aid=1283895&group_id=5470&atid=105470 [1] http://www.jensdiemer.de/Programmieren/Python/PyDown [2] http://kofoto.rosdahl.net/trac/wiki/UnicodeInPython [3] http://wsgiarea.pocoo.org/jinja/ [4] http://www.python-forum.de/viewtopic.php?p=34275#34275 -- Mfg. Jens Diemer ---- CMS in pure Python CGI: http://www.pylucid.org _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
jens wrote:
Eigentlich sollte os.unlink(u"path") alle Verz. Einträge als unicode zurück liefern.
Du meinst wohl os.listdir. os.unlink liefert nichts zurück :-)
Das tut es allerdings nicht wirklich. Unter Windows geht's unter Linux gibt's Probleme, da Einträge mit Sonderzeichen bei mir kein Unicode sind :(
Damit das funktioniert, musst Du Deine locale richtig einstellen. Leider gibt es unter Linux kein anderes Verfahren, um das Encoding des Dateisystems zu ermitteln, außer der locale. Deshalb fragt Python nach dem encoding der locale. Wenn Deine Dateinamen beispielsweise mit ISO-8859-1 kodiert sind, könnte es helfen, LANG auf de_DE, oder vielleicht auch auf de_DE.ISO-8859-1 zu setzen.
Doch selbst wenn man alle Verz.-Einträge als unicode hat, gibt es Probleme mit einigen Python "Befehlen"... Denn nicht alle mögen Unverständnisserweise unicode. z.B. os.path.*
Welche Python-Funktion hat den Probleme, und worin äußern die sich? Ciao, Martin _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Martin v. Löwis schrieb:
Du meinst wohl os.listdir. os.unlink liefert nichts zurück :-)
Klar, meinte ich os.listdir... sorry...
Deshalb fragt Python nach dem encoding der locale. Wenn Deine Dateinamen beispielsweise mit ISO-8859-1 kodiert sind, könnte es helfen, LANG auf de_DE, oder vielleicht auch auf de_DE.ISO-8859-1 zu setzen. Meine locale sind alle (außer LC_ALL) auf "de_DE.UTF-8" eingestellt.
Ich hab mir TestDaten gemacht: <verz> ./dir eins/ <verz> ./dir zwei äöüß/ <datei> ./file eins.txt <datei> ./file zwei äöüß.txt Im mc sehe ich die Namen richtig. Mit dem ls Befehl allerdings nicht. Da sind nur Fragezeichen statt den Umlauten.
Welche Python-Funktion hat den Probleme, und worin äußern die sich?
Also ich mache es nun so. Wenn ein item von os.listdir() kein unicode ist, probiere ich verschiedene codecs durch (latin-1, utf-8, ascii) und einer passt dann auch. Im Ergebniss hab ich dann also alle items in unicode... Nun kann ich damit aber irgendwie nix mehr anfangen, weil os.stat() z.B. die Dateien nicht mehr findet und auch os.path.isfile bzw. isdir nicht mehr fündig werden. Also hab ich nochmal ein neuen Test gemacht. Diesmal hab ich per Samba von Windows aus neue Dateien mit Umlauten gemacht. Siehe da, nun klappt es direkt! Also os.listdir() spuckt direkt unicode aus und os.stat() und os.path.* arbeiten richtig. Das komische ist, das ich auf der Konsole folgendes für äöüß sehe: äöüà - Was für mich aussieht wie UTF-8. String Escaped ist das: \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x9f Das für beide Fälle. Also einmal bei den Dateien die ich direkt auf dem Ubuntu-Rechner erzeugt hab und einmal die Dateien die ich per Samba erstellt hab. Ein Unterschied sieht man allerdings im mc! Die durch Samba erstellten Dateien sehe ich nur mit äöüà die unter Linux erstellten Dateien sehe ich richtig mit äöüß Also liegt das ganze Problem wohl an meiner Linux installation :( Nur sollte Python in dem Falle nicht irgendwie trotzdem funktionieren? Kompliziert wird es, weil ich ja die Dateinamen als Webseite anzeigen lasse, mit Links. Diese Links sollten auch funktionieren ;) -- Mfg. Jens Diemer ---- CMS in pure Python CGI: http://www.pylucid.org _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
jens wrote:
Ich hab mir TestDaten gemacht: <verz> ./dir eins/ <verz> ./dir zwei äöüß/ <datei> ./file eins.txt <datei> ./file zwei äöüß.txt
Im mc sehe ich die Namen richtig. Mit dem ls Befehl allerdings nicht. Da sind nur Fragezeichen statt den Umlauten.
Dann sind die Umlaute vermutlich mit ISO-8859-1 kodiert, und nicht mit UTF-8. Schalte Deine locale mal auf ISO-8859-1, und probier dann ls noch mal. Alternativ: Erzeuge mal eine Datei "ohne" mc, z.B. mit touch äöu.txt Probier' dann ls, und dann mc. Solange das alles nicht zusammen passt, ist es kein Wunder, wenn Python damit nicht klar kommt.
Also hab ich nochmal ein neuen Test gemacht. Diesmal hab ich per Samba von Windows aus neue Dateien mit Umlauten gemacht. Siehe da, nun klappt es direkt! Also os.listdir() spuckt direkt unicode aus und os.stat() und os.path.* arbeiten richtig.
Samba nimmt per default an, dass Dateinamen unter Linux UTF-8-kodiert sind (Einstellung "unix charset", siehe smb.conf(5)).
Also liegt das ganze Problem wohl an meiner Linux installation :(
Genau. Du musst Dich entscheiden, welches Encoding Dateinamen auf Deinem System haben sollen, und dass dann konsequent konfigurieren. Meine Empfehlung: Dateinamen sollten UTF-8-kodiert sein. Da Deine locale schon richtig ist, musst Du nun noch Deine Terminalemulation anpassen. Wie man das macht, hängt vom konkreten Programm ab. Bei (KDEs) konsole kannst Du beispielsweise mal echo $'\033%G' ausführen: das schaltet die konsole in UTF-8-Modus. Wenn Du dann ls machst, sollten die Samba-erzeugten Dateinamen richtig angezeigt werden. Alternativ kannst Du das encoding auch über Einstellungen/Kodierung umschalten.
Nur sollte Python in dem Falle nicht irgendwie trotzdem funktionieren?
Nein, das ist technisch nicht möglich. Du hast (über die locale) Python erklärt, dass Deine Dateinamen UTF-8-kodiert sind. Es liest (mittels readdir) die Dateinamen ein, und stellt fest, dass es nicht UTF-8 sein *kann*. Was es dann aber ist, kann es nicht wissen, und fügt deshalb byte strings in das listdir-Ergebnis ein.
Kompliziert wird es, weil ich ja die Dateinamen als Webseite anzeigen lasse, mit Links. Diese Links sollten auch funktionieren ;)
Ja, an dieser Stelle hat Unix große Mängel. Langfristig die einzige Lösung ist die Verwendung nur noch von UTF-8 locales, und die durchgängige Verwendung dieses Encodings in Dateinamen, Daten usw. Ciao, Martin _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Martin v. Löwis schrieb:
Also liegt das ganze Problem wohl an meiner Linux installation :(
Genau. Du musst Dich entscheiden, welches Encoding Dateinamen auf Deinem System haben sollen, und dass dann konsequent konfigurieren.
Jep, das ist es... Ich hab mal ein "sudo dpkg-reconfigure locales" gemacht und nur "de_DE.UTF-8" ausgewählt. Sieht da, mit ls sehe ich nun alles korrekt. Mein TestSkript funktioniert auch und os.listdir() spuckt nur unicode raus... Dennoch will meine WebApp nicht :( In meinem kleinen TestSkript hab ich folgendes: ======================================================================= def get_file_encoding(f): if hasattr(f, "encoding"): return f.encoding else: return "not set" print "sys.stdin.encoding:", get_file_encoding(sys.stdin) print "sys.stdout.encoding:", get_file_encoding(sys.stdout) print "sys.stderr.encoding:", get_file_encoding(sys.stderr) print "sys.getdefaultencoding():", sys.getdefaultencoding() print "sys.getfilesystemencoding():", sys.getfilesystemencoding() print "locale.getpreferredencoding():", locale.getpreferredencoding() ======================================================================= Das spukt mir das aus: """ sys.stdin.encoding: UTF-8 sys.stdout.encoding: UTF-8 sys.stderr.encoding: None sys.getdefaultencoding(): ascii sys.getfilesystemencoding(): UTF-8 locale.getpreferredencoding(): UTF-8 """ Sieht also gut aus... Nun hab ich es mal in meiner WebApp eingebaut und siehe da, es sind ganz andere Angaben: """ sys.stdin.encoding: None sys.stdout.encoding: None sys.stderr.encoding: None sys.getdefaultencoding(): ascii sys.getfilesystemencoding(): ANSI_X3.4-1968 locale.getpreferredencoding(): ANSI_X3.4-1968 """ Vorsorglich hab ich mal apache restartet, bring aber auch nix... Wie kommt es, das hier völlig andere Angaben zustandekommen? Ich nehme mal an, das Python darüber stolpert... Leider kann man ja nicht per sys.setdefaultencoding() ein eigenes einstellen, da es von site.py gelöscht wird :( Mit einem reload kann man es allerdings doch machen: reload(sys) sys.setdefaultencoding("utf-8") Bringt aber in meinem Falle auch nicht's :( Zwar ist sys.getdefaultencoding() danach wirklich auf UTF-8 umgestellt, aber sys.getfilesystemencoding() und locale.getpreferredencoding() bleiben auch den alten Werten... Also von daher bin ich leider nicht wirklich weiter :( -- Mfg. Jens Diemer ---- CMS in pure Python CGI: http://www.pylucid.org _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Jens Diemer wrote:
Sieht also gut aus... Nun hab ich es mal in meiner WebApp eingebaut und siehe da, es sind ganz andere Angaben:
""" sys.stdin.encoding: None sys.stdout.encoding: None sys.stderr.encoding: None sys.getdefaultencoding(): ascii sys.getfilesystemencoding(): ANSI_X3.4-1968 locale.getpreferredencoding(): ANSI_X3.4-1968 """
Offenbar läuft Apache mit LANG=C. Es gibt zwei Möglichkeiten: 1. Du änderst die locale, in der Apache läuft, z.B. indem Du in /etc/init.d/apache2 den Text ENV="env -i LANG=C PATH=/usr/local/bin:/usr/bin:/bin" durch ENV="env -i LANG=de_DE.UTF-8 PATH=/usr/local/bin:/usr/bin:/bin" ersetzt (besser würde man ENV in /etc/default/apache2 setzen) 2. Du änderst LANG nur für das CGI-Skript, etwa mittels SetEnv: http://httpd.apache.org/docs/2.0/mod/mod_env.html#passenv Ciao, Martin _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Martin v. Löwis schrieb:
Offenbar läuft Apache mit LANG=C. Es gibt zwei Möglichkeiten:
1. Du änderst die locale, in der Apache läuft, z.B. indem Du in /etc/init.d/apache2 den Text
ENV="env -i LANG=C PATH=/usr/local/bin:/usr/bin:/bin"
durch
ENV="env -i LANG=de_DE.UTF-8 PATH=/usr/local/bin:/usr/bin:/bin"
ersetzt (besser würde man ENV in /etc/default/apache2 setzen)
2. Du änderst LANG nur für das CGI-Skript, etwa mittels SetEnv:
Der erste "Patch" funktioniert! Die zweite Variante hat spontan nicht funktioniert... Danke! Nun bin ich ein Stück weiter ;) Nun sieht es so aus: """ sys.stdin.encoding: None sys.stdout.encoding: None sys.stderr.encoding: None sys.getdefaultencoding(): ascii sys.getfilesystemencoding(): UTF-8 locale.getpreferredencoding(): UTF-8 """ Nun hab ich endlich alle Dateinamen in unicode... Aber es taucht direkt das nächste Problem auf :( urllib.quote() wirft einen KeyError: """ File "./FilesystemUnicodeTest.py", line 81, in filesystemTest print urllib.quote(abs_path) File "/usr/lib/python2.4/urllib.py", line 1107, in quote res = map(safe_map.__getitem__, s) KeyError: u'\xf6' """ Er stolpert über ein "ö"... Es geht allerdings , wenn ich urllib.quote(abs_path.encode("utf-8")) mache... Ist das normal? -- Mfg. Jens Diemer ---- CMS in pure Python CGI: http://www.pylucid.org _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Jens Diemer wrote:
Es geht allerdings , wenn ich urllib.quote(abs_path.encode("utf-8")) mache... Ist das normal?
Jein. URLs sind (bedauerlicherweise) Bytestrings und nicht lesbarer Text (*); dass man sie in HTML integriert hat, war unsauber (genauer: es war unsauber, dass man URLs als Bytestrings definiert hat). urllib.quote unterstützt nur byte strings. Das encoding eines URLs muss der Webserver selber wissen: er hat den URL ausgegeben, er muss die Resource auflösen können... Das Problem wird langfristig von IRIs gelöst (Internationalized Resource Identifiers); bei denen handelt es sich um Text. Wie man IRIs in Python und Apache integriert, ist noch offen. Kurz: Denk Dir ein Encoding für Deine URLs aus, und verwende das einheitlich. UTF-8 ist eine naheliegende Wahl. Ciao, Martin (*) eine andere Interpretation ist, dass URLs nur ASCII unterstützen _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Danke für deine Hilfe... Ich mach es nun einfach so: url = urllib.quote(url.encode("utf-8")) und zurück mit url = unicode(urllib.unquote(url), "utf-8") Das klappt bei mir bisher unter Windows und Linux... -- Mfg. Jens Diemer ---- CMS in pure Python CGI: http://www.pylucid.org _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Martin v. Löwis schrieb:
1. Du änderst die locale, in der Apache läuft, z.B. indem Du in /etc/init.d/apache2 den Text 2. Du änderst LANG nur für das CGI-Skript, etwa mittels SetEnv:
Hab jetzt nochmal nachgesehen und probiert (Hatte ja spontan nur mit dem Patch von /etc/init.d/apache2 geklappt) Mit SetEnv kann man das ganze gezielt per .htaccess nur für das CGI-Script machen, so wie du es vorgeschlagen hast. Das sieht dann so aus: SetEnv LANG de_DE.UTF-8 siehe auch: http://httpd.apache.org/docs/2.0/mod/mod_env.html#setenv Dank dir nochmal ;) -- Mfg. Jens Diemer ---- CMS in pure Python CGI: http://www.pylucid.org _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
Jens Diemer schrieb:
SetEnv LANG de_DE.UTF-8 siehe auch: http://httpd.apache.org/docs/2.0/mod/mod_env.html#setenv
Da PyDown ja WSGI kompatibel ist, wollte ich gleich mal die fastCGI Variante ausprobieren. Dabei hab ich festgestellt, das man die LANG Variable für fastCGI nochmal separat setzten muß :( Dazu hab ich in der apache2.conf folgendes eingetragen: <IfModule mod_fastcgi.c> FastCgiConfig -initial-env LANG=de_DE.UTF-8 </IfModule> Damit geht's ;) -- Mfg. Jens Diemer ---- CMS in pure Python CGI: http://www.pylucid.org _______________________________________________ python-de maillist - python-de@python.net http://python.net/mailman/listinfo/python-de
participants (3)
-
"Martin v. Löwis"
-
jens
-
Jens Diemer