2009-05-11 1 views
26

Windows에서 유니 코드 명령 행 인자를 읽을 수 있도록 Python 스크립트를 만들고 싶습니다. 그러나 sys.argv는 유니 코드가 아닌 일부 로컬 인코딩으로 인코딩 된 문자열입니다. 전체 유니 코드로 명령 줄을 읽으려면 어떻게해야합니까?Windows의 Python 2.x에서 명령 행 인자에서 유니 코드 문자 읽기

예제 코드 :

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> 

그의 시프트-JIS 내가 생각 인코딩, 그리고 "작품"그것에 대해 : 일본어 코드 페이지 설정 내 PC에 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) 

, 내가 얻을 파일 이름.

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' 

주 - 난 3.0 파이썬, 파이썬 2.X에 대해하지 말 :하지만 설정 최종 "열기"호출이 실패하려면 Shift-JIS 문자가 아닌 문자로 파일 이름을 바꿈. 나는 파이썬 3.0이 적절한 유니 코드 인 sys.argv을 제공한다는 것을 발견했다. 그러나 아직 파이썬 3.0으로 전환하기에는 아직 시기상비가 있습니다 (타사 라이브러리 지원이 없기 때문에).

업데이트 : 몇 가지 답변 내가 sys.argv가 인코딩됩니다 무엇에 따라 디코딩한다 말한 그의 문제는 그것이 아니라 전체 유니 코드입니다 그래서 일부 문자는 표현할 수없는 것입니다

..

나를 슬프게하는 유스 케이스는 다음과 같습니다. enabled drag-and-drop of files onto .py files in Windows Explorer입니다. 시스템 기본 코드 페이지에없는 문자를 포함하여 모든 종류의 문자가 포함 된 파일 이름이 있습니다. 내 Python 스크립트는 현재 코드 페이지 인코딩에서 문자를 표현할 수없는 모든 경우에 sys.argv를 통해 전달되는 올바른 유니 코드 파일 이름을 얻지 못합니다.

전체 유니 코드로 명령 줄을 읽는 Windows API가 있습니다 (Python 3.0에서는이 기능을 제공합니다). 나는 파이썬 2.x 인터프리터가 그것을 사용하지 않는다고 가정한다.

+0

는 일본어 Windows는 기본적으로 콘솔에 래스터 글꼴을 사용합니까? 이렇게하면 Windows-932 코드 페이지에 문자를 표시하는 데 제한 될 수 있습니다. http://support.microsoft.com/kb/Q99795를 참조하십시오 (이것은 args를 읽는 것에 대한 별도의 문제이지만 약간의 영향을 미칠 수 있습니다) – McDowell

+0

Stack Overflow에서이 질문을 확인하면 질문에 대한 답을 제공해야합니다. http://stackoverflow.com/questions/477061/how-to-read-unicode-input-and-compare-unicode-strings-in-python – AlbertoPL

+0

예, 정확한 dup 인 것으로 보입니다. –

답변

27

키 레지스트리에서 적절한 인코딩 이름을 추론 할 수 있어야하는 것은 내가 찾고 윈도우 GetCommandLineArgvW 함수에 대한 호출을 만들고있어 단지 무엇을하는 솔루션입니다 :
Get sys.argv with Unicode characters under Windows

(ActiveState의에서)

하지만 사용법을 간소화하고 특정 용도를 다루기 위해 몇 가지 변경을했습니다.

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() 

, 나는 그것을 사용하는 방법이해야하는 것입니다 : 여기에 내가 무엇을 사용

import sys 
import win32_unicode_argv 

다음부터를 sys.argv는 유니 코드의 목록입니다 문자열. 파이썬 optparse 모듈은 그것을 분석하는 것이 행복해 보입니다.

+0

네, 그게 효과가 있습니다. 그냥 끝내 ".encode ('utf-8')"을 제거하십시오 –

+0

py 파일로 파일을 끌어다 놓을 때이 코드 조각이 작동하지 않습니다. 그러나이 코드는 명령 프롬프트에 파일 이름을 입력 할 때 작동합니다. 그리고 GetCommandLineW를 호출하기 위해 C++ 프로그램을 작성했습니다. 프로그램에 파일을 끌어서 놓으면 프로그램에서 파일 이름을 올바르게 표시 할 수 있습니다. – franziga

+0

@ franziga : "작동하지 않는"것은 구체적으로 무엇을 의미합니까? [Python 파일로 드래그 앤 드롭 가능] (http://stackoverflow.com/q/142844/60075)해야합니다. 이 작업을 수행한지 얼마되지 않아서 (그리고 다른 회사에서) 긴 파일 이름을 활성화해야한다고 생각합니다. –

0

명령 줄은 Windows 인코딩 일 수 있습니다. unicode 객체로 인수를 디코딩 시도 :

args = [unicode(x, "iso-8859-9") for x in sys.argv] 
+0

sys.args -> sys.argv – pts

+0

감사합니다. 고정 .... –

+2

-1 "iso-8859-9"는 Windows 인코딩이 아닙니다. 방금 문제가 악화되었습니다. –

2

이 시도 :

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

은 어쩌면 당신은 UTF-8에 대한 CP437 또는 CP1252을 대체해야합니다. 당신은 여기 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage\OEMCP

10

인코딩을 다루는 것은 매우 혼란 스럽습니다.

명령 줄을 통해 데이터를 입력하면 시스템 인코딩과 유니 코드가 아닌 데이터가 인코딩됩니다. · 프롬프트> 파이썬 myargv.py "PC :

(심지어 붙여 넣기이 작업을 수행해야/복사) 그래서 시스템 인코딩 사용하여 유니 코드로 디코딩 정확해야 다음 윌 출력을 실행

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()) 

을ソ フ ト 申請書 08.09.24.txt "

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

어디"PC · ソ フ ト 申請書 08.09.24.txt 日本語 ""텍스트를 포함 ". (필자는 Windows 메모장을 사용하여 utf8로 파일을 인코딩 했으므로 인쇄 할 때 '?'가 시작되는 이유에 대해 다소 혼란 스럽습니다.) 메모장에서 utf8을 저장하는 방법과 관련이 있습니다.)

문자열 '디코드 '메서드 또는 unicode() 내장 코드를 사용하여 인코딩을 유니 코드로 변환 할 수 있습니다.

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

또한, 인코딩 된 파일과의 거래는 내장 된 개방() 대신에 codecs.open() 함수를 사용 할 수 있습니다합니다. 그것은 당신이 파일의 인코딩을 정의 할 수있게하고, 주어진 인코딩을 사용하여 투명하게 컨텐트를 유니 코드로 디코딩합니다.

전화 할 때 content = codecs.open("myfile.txt", "r", "utf8").read()content은 유니 코드입니다.

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

내가 미스-이해 뭔가를 해요 경우 알려 주시기 바랍니다.

이미 내가 유니 코드 및 인코딩에 조엘의 기사를 읽어 보시기 바랍니다하지 않은 경우 : http://www.joelonsoftware.com/articles/Unicode.html