Domanda

Voglio che il mio script Python per essere in grado di leggere gli argomenti della riga di comando Unicode in Windows. Ma sembra che sys.argv è una stringa codificata in qualche codifica locale, anziché Unicode. Come posso leggere la riga di comando in Unicode completo?

Esempio di codice: argv.py

import sys

first_arg = sys.argv[1]
print first_arg
print type(first_arg)
print first_arg.encode("hex")
print open(first_arg)

Sul mio PC configurato per la pagina di codice giapponese, ottengo:

C:\temp>argv.py "PC・ソフト申請書08.09.24.doc"
PC・ソフト申請書08.09.24.doc
<type 'str'>
50438145835c83748367905c90bf8f9130382e30392e32342e646f63
<open file 'PC・ソフト申請書08.09.24.doc', mode 'r' at 0x00917D90>

Quella Shift-JIS codificato credo, e "funziona" per quel nome di file. Ma si rompe per i nomi di file con caratteri che non sono nel carattere Shift-JIS set-la chiamata finale "aperto" fallisce:

C:\temp>argv.py Jörgen.txt
Jorgen.txt
<type 'str'>
4a6f7267656e2e747874
Traceback (most recent call last):
  File "C:\temp\argv.py", line 7,
in <module>
    print open(first_arg)
IOError: [Errno 2] No such file or directory: 'Jorgen.txt'

Nota-sto parlando Python 2.x, non Python 3.0. Ho scoperto che Python 3.0 dà sys.argv come proprio Unicode. Ma è un po 'ancora presto per passare a Python 3.0 (a causa della mancanza di supporto delle librerie terze parti).

Aggiornamento:

A poche risposte hanno detto che dovrei decodificare in base a tutto ciò che la <=> è codificato in. Il problema di questo è che non è Unicode completo, per cui alcuni personaggi non sono rappresentabili.

Ecco il caso d'uso che mi dà dolore: ho abilitato drag-and-drop dei file su file .py in Esplora risorse . Ho i nomi di file con tutti i tipi di personaggi, tra cui alcuni non nella pagina di codice predefinita del sistema. Il mio script Python non ottenere il giusto nomi di file Unicode passati ad esso tramite sys.argv in tutti i casi, quando i personaggi non sono rappresentabili nella codifica tabella codici corrente.

Non è certamente un po 'API di Windows per leggere la riga di comando con piena Unicode (e Python 3.0 lo fa). Suppongo che l'interprete Python 2.x non lo utilizza.

È stato utile?

Soluzione

Ecco una soluzione che è proprio quello che sto cercando, facendo una chiamata alla funzione di Windows GetCommandLineArgvW:
Get sys.argv con caratteri Unicode in Windows (da ActiveState)

Ma ho fatto diversi cambiamenti, per semplificare il suo utilizzo e gestire meglio alcuni usi. Ecco quello che io uso:

win32_unicode_argv.py

"""
win32_unicode_argv.py

Importing this will replace sys.argv with a full Unicode form.
Windows only.

From this site, with adaptations:
      http://code.activestate.com/recipes/572200/

Usage: simply import this module into a script. sys.argv is changed to
be a list of Unicode strings.
"""


import sys

def win32_unicode_argv():
    """Uses shell32.GetCommandLineArgvW to get sys.argv as a list of Unicode
    strings.

    Versions 2.x of Python don't support Unicode in sys.argv on
    Windows, with the underlying Windows API instead replacing multi-byte
    characters with '?'.
    """

    from ctypes import POINTER, byref, cdll, c_int, windll
    from ctypes.wintypes import LPCWSTR, LPWSTR

    GetCommandLineW = cdll.kernel32.GetCommandLineW
    GetCommandLineW.argtypes = []
    GetCommandLineW.restype = LPCWSTR

    CommandLineToArgvW = windll.shell32.CommandLineToArgvW
    CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(c_int)]
    CommandLineToArgvW.restype = POINTER(LPWSTR)

    cmd = GetCommandLineW()
    argc = c_int(0)
    argv = CommandLineToArgvW(cmd, byref(argc))
    if argc.value > 0:
        # Remove Python executable and commands if present
        start = argc.value - len(sys.argv)
        return [argv[i] for i in
                xrange(start, argc.value)]

sys.argv = win32_unicode_argv()

Ora, il modo in cui lo uso è semplicemente quello di fare:

import sys
import win32_unicode_argv

e da allora in poi, sys.argv è una lista di stringhe Unicode. Il modulo di Python optparse sembra felice di analizzarlo, che è grande.

Altri suggerimenti

Si occupano di codifiche è molto confuso.

I credo se i dati inputing tramite la riga di comando che si codificare i dati come ciò che la codifica del sistema è e non è Unicode. (Anche copia / incolla dovrebbe fare questo)

Così dovrebbe essere corretto per decodificare in Unicode utilizzando la codifica di sistema:

import sys

first_arg = sys.argv[1]
print first_arg
print type(first_arg)

first_arg_unicode = first_arg.decode(sys.getfilesystemencoding())
print first_arg_unicode
print type(first_arg_unicode)

f = codecs.open(first_arg_unicode, 'r', 'utf-8')
unicode_text = f.read()
print type(unicode_text)
print unicode_text.encode(sys.getfilesystemencoding())

eseguendo il seguente output:     Prompt> python myargv.py "PC · ソ フ ト 申請書 08.09.24.txt"

PC・ソフト申請書08.09.24.txt
<type 'str'>
<type 'unicode'>
PC・ソフト申請書08.09.24.txt
<type 'unicode'>
?日本語

Se il "PC · ソ フ ト 申請書 08.09.24.txt" contenuto del testo, "日本語". (I codificato il file come utf8 utilizzando Blocco note di Windows, sono un po 'perplesso sul motivo per cui c'è un '?' Nell'inizio durante la stampa. Qualcosa a che fare con il modo di risparmiare notepad utf8?)

Il metodo stringhe 'decodificare' o unicode () integrato può essere utilizzato per convertire una codifica in unicode.

unicode_str = utf8_str.decode('utf8')
unicode_str = unicode(utf8_str, 'utf8')

Inoltre, se il trattare con i file codificati si consiglia di utilizzare la funzione codecs.open () al posto del built-in open (). Esso consente di definire la codifica del file, e verrà quindi utilizzare la codifica data per decodificare in modo trasparente il contenuto in Unicode.

Così, quando si chiama content = codecs.open("myfile.txt", "r", "utf8").read() content sarà in unicode.

codecs.open: http://docs.python.org/library/codecs.html?#codecs .Open

Se io sono miss-capire qualcosa fatemelo sapere.

Se non l'hai già vi consiglio di leggere l'articolo di Joel su unicode e la codifica: http://www.joelonsoftware.com/articles/Unicode.html

Prova questo:

import sys
print repr(sys.argv[1].decode('UTF-8'))

Forse devi sostituire CP437 o CP1252 per UTF-8. Si dovrebbe essere in grado di dedurre il nome della codifica corretta dalla chiave di registro HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage\OEMCP

La riga di comando potrebbe essere nella codifica di Windows. Prova la decodifica gli argomenti nei unicode oggetti:

args = [unicode(x, "iso-8859-9") for x in sys.argv]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top