Seite 1 von 1

Unicode und argv

Verfasst: Freitag 29. Juni 2007, 13:35
von tb71
Hallo,

fange gerade neu mit Python an und stehe schon vor einem (für mich unlösbaren) Problem: Wie kann ich Parameter mit nicht 8-bit-Zeichen übergeben/auswerten, z.B.:

ασγξκ3ς

Der Aufruf des Scripts erfolgt von der Kommandozeile, der Output (einfach nur Traces) geht in eine Datei um Probleme mit dem Encoding der Konsole auszuschließen:

Code: Alles auswählen

# pyargs: print information about the script arguments
import sys
import codecs
OUT = codecs.open("output.txt",encoding="utf-16",mode="w")
s1 = u"pyargs: %d arguments passed\r\n" % len(sys.argv);
OUT.write(s1)
for i in sys.argv:
  s2 = i.decode(argv_encoding)
  s2 = u"pyargs: argument " + s2 + "\r\n"
  OUT.write(s2)
OUT.close()
Ach ja, Python 2.5.1 unter Windows (XP).

Leider habe ich bislang trotz intensiver Suche noch keine Lösung gefunden. Auch ein Start des Interpreters mit Parameter "-U" hat keine Auswirkung.

Liebe Grüße und schon mal Danke im Voraus!

Thomas

Verfasst: Freitag 29. Juni 2007, 15:15
von BlackJack
Der Quelltext dürfte einen NameError provozieren, weil `argv_encoding` nirgends gebunden wird.

Wie die Daten in `sys.argv` kodiert sind, hängt vom aufrufenden Programm ab. Da musst Du entweder raten und hoffen, dass Deine Annahmen stimmen, oder dem Benutzer die Möglichkeit geben eine Kodierung explizit als Option dem Programm mit auf den Weg zu geben.

Die Frage ist am Anfang übrigens etwas unpräzise: Ob Zeichen mit 8 Bit darstellbar sind, oder nicht, hängt auch von der Kodierung ab. Das Beispiel lässt sich als iso-8859-7 kodiert nämlich durchaus mit 8 Bit pro Zeichen darstellen.

Re: Unicode und argv

Verfasst: Freitag 29. Juni 2007, 15:19
von lunar
tb71 hat geschrieben:

Code: Alles auswählen

# pyargs: print information about the script arguments
import sys
import codecs
OUT = codecs.open("output.txt",encoding="utf-16",mode="w")
s1 = u"pyargs: %d arguments passed\r\n" % len(sys.argv);
OUT.write(s1)
for i in sys.argv:
  s2 = i.decode(argv_encoding)
  s2 = u"pyargs: argument " + s2 + "\r\n"
  OUT.write(s2)
OUT.close()
Dieser Code ist so nicht lauffähig, da argv_encoding überhaupt nicht definiert ist. Vielleicht solltest du mal sys.getfilesystemencoding ausprobieren. Auch das Wiki schadet nie: [wiki]Von Umlauten, Unicode und Encodings[/wiki]

Verfasst: Freitag 29. Juni 2007, 15:45
von Masaru
Leider ist sys.getfilesystemencoding() keine 100%ige Absicherung dafür, dass auch das, was hinneinkommt, wirklich in dem Codec codiert ist.

Zudem kann auf einigen Betriebssystemen die Methode "None" zurückliefern (z.B. HP-UX) was denn die .decode() Methode crashen lässt (erwartet schließlich ein String).

>>Masaru<<

Verfasst: Freitag 29. Juni 2007, 15:57
von lunar
Masaru hat geschrieben:Zudem kann auf einigen Betriebssystemen die Methode "None" zurückliefern (z.B. HP-UX) was denn die .decode() Methode crashen lässt (erwartet schließlich ein String).
Tja, selbst schuld, wer so exotisches Zeuch einsetzt ;)

Vielleicht kann man sich ja auch von Gerolds encodinghelper.py Anregungen zum Bestimmen des Encodings holen.

Verfasst: Montag 2. Juli 2007, 08:07
von tb71
Hallo,
Masaru hat geschrieben:Leider ist sys.getfilesystemencoding() keine 100%ige Absicherung dafür, dass auch das, was hinneinkommt, wirklich in dem Codec codiert ist.

Zudem kann auf einigen Betriebssystemen die Methode "None" zurückliefern (z.B. HP-UX) was denn die .decode() Methode crashen lässt (erwartet schließlich ein String).
Was fehlte, war im Code ein

Code: Alles auswählen

argv_encoding = sys.getfilesystemencoding()
Das beschriebene Verhalten ist leider trotzdem wie angemerkt.

So exotisch ist mein Wunsch ja (denke ich) eigentlich nicht, dass Parameter unter Windows auch korrekt vom Script verarbeitet werden können.

Aufgerufen wird das ganze aus cmd.exe (unter Windows XP), ein C-Programm kriegt die Parameter ganz korrekt als Unicode mit wenn vom Betriebssystem mittels Unicode-API erfragt.

Nur leider scheints bei jedem zu funktionieren (ich finde dazu leider in der Dokumentation bzw. per google nichts relevantes) nur bei mir nicht und ich frage mich warum

lg.
Thomas[/code]

Verfasst: Montag 2. Juli 2007, 09:51
von tb71
Hallo,

nur für den Fall, dass es jemanden interessiert hier meine Lösung:

Command Line auslesen mittels

Code: Alles auswählen

ctypes.windll.kernel32.GetCommandLineW()
Die API

Code: Alles auswählen

[win32api|win32ui].GetCommandLine()
geht nicht (kein Unicode...)

Mittels

Code: Alles auswählen

ctypes.windll.shell32.CommandLineToArgvW()
splitten.

Wenns "schöner" geht, bin ich für jeden Input dankbar.

lg.
Thomas