Python, 유니 코드 및 Windows 콘솔


145

Windows 콘솔에서 유니 코드 문자열을 인쇄하려고하면 UnicodeEncodeError: 'charmap' codec can't encode character ....오류가 발생합니다. Windows 콘솔은 유니 코드 전용 문자를 허용하지 않기 때문이라고 생각합니다. 이 문제를 해결하는 가장 좋은 방법은 무엇입니까? ?이 상황에서 Python이 자동으로 인쇄하는 대신 실패 하게 만드는 방법 이 있습니까?

편집 : Python 2.5를 사용하고 있습니다.


참고 : 체크 표시가있는 @ LasseV.Karlsen 답변은 오래된 것입니다 (2008 년부터). 아래의 솔루션 / 응답 / 제안을주의해서 사용하십시오 !!

@JFSebastian의 답변 은 오늘 (2016 년 1 월 6 일)보다 관련성이 높습니다 .


어떤 버전의 Python을 사용하고 있습니까? 나는 이것이 2.4.3에서 깨졌고 2.4.4에서 수정되었다는 언급을 보았다.
Stu



1
내가 찾은 가장 간단한 대답은 다음과 같이 입력하는 것입니다. cmd에서 pyhton을 사용하기 전에 chcp 65001
Soorena

1
그럼 당신은 당신의 수락 답변을 변경해야합니다 ...
Mr_and_Mrs_D

답변:


38

참고 : 이 답변은 구식입니다 (2008 년부터). 아래 솔루션을주의해서 사용하십시오 !!


다음은 문제와 해결책을 자세히 설명하는 페이지입니다 ( rap.sys.stdout 텍스트를 인스턴스로 랩핑 하는 페이지 검색 ).

PrintFails-파이썬 위키

해당 페이지에서 발췌 한 코드는 다음과 같습니다.

$ python -c 'import sys, codecs, locale; print sys.stdout.encoding; \
    sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout); \
    line = u"\u0411\n"; print type(line), len(line); \
    sys.stdout.write(line); print line'
  UTF-8
  <type 'unicode'> 2
  Б
  Б

  $ python -c 'import sys, codecs, locale; print sys.stdout.encoding; \
    sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout); \
    line = u"\u0411\n"; print type(line), len(line); \
    sys.stdout.write(line); print line' | cat
  None
  <type 'unicode'> 2
  Б
  Б

그 페이지에 더 많은 정보가 있으며 읽을 가치가 있습니다.


7
링크가 죽었고 답변의 요점은 인용되지 않았습니다. -1
0xC0000022L

1
랩핑 sys.stdout에 대한 주어진 조언을 시도 하면 잘못된 것을 인쇄합니다. 예를 들어, 대시 대신에 u'\u2013'됩니다 û.
user2357112는

@ user2357112 이에 대한 새로운 질문을 게시해야합니다. 유니 코드와 시스템 콘솔이 반드시 가장 좋은 조합은 아니지만 이것에 대해 충분히 알지 못하므로 명확한 대답이 필요하면 여기에 대한 질문을 게시하십시오.
Lasse V. Karlsen

2
링크가 죽었습니다. 와 같은 코드 페이지 (OEM) cp437가 Windows ANSI 코드 페이지와 다른 Windows 콘솔의 경우 코드 예제가 잘못 되었습니다 cp1252. 코드가 해결되지 않는 UnicodeEncodeError: 'charmap' codec can't encode character오류 및 글자 깨짐 등으로 이어질 수, ا©자동으로 대체됩니다 ╪º⌐.
jfs

73

업데이트 : 파이썬 3.6 구현의 PEP 528 : UTF-8로 변경 Windows 콘솔 인코딩 : Windows에서 기본 콘솔은 이제 모든 유니 코드 문자를 사용할 수 있습니다. 내부적으로는 같은 유니 코드 API 사용 아래에 언급 된 패키지를 . 지금 작동해야합니다.win-unicode-consoleprint(unicode_string)


내가 얻을 UnicodeEncodeError: 'charmap' codec can't encode character... 오류입니다.

이 오류는 인쇄하려는 유니 코드 문자를 현재 ( chcp) 콘솔 문자 인코딩 으로 표현할 수 없음을 의미합니다 . 코드 페이지는 종종 cp437~ 1M 유니 코드 문자에서 ~ 0x100 문자 만 나타낼 수있는 8 비트 인코딩입니다 .

>>> u "\ N {EURO SIGN}". encode ( 'cp437')
역 추적 (가장 최근 통화) :
...
UnicodeEncodeError : 'charmap'코덱은 위치 0에서 '\ u20ac'문자를 인코딩 할 수 없습니다.
캐릭터는 

Windows 콘솔은 유니 코드 전용 문자를 허용하지 않기 때문이라고 생각합니다. 이 문제를 해결하는 가장 좋은 방법은 무엇입니까?

Windows 콘솔은 유니 코드 문자를 허용 하며 해당 글꼴이 구성된 경우 해당 문자를 표시 할 수도 있습니다 (BMP 만 해당) . @Daira Hopwood의 답변WriteConsoleW() 에서 제안한대로 API를 사용해야합니다 . 패키지를 투명하게 호출 할 수 있습니다. 즉, package 를 사용하면 스크립트를 수정하지 않아도됩니다 .win-unicode-console

T:\> py -mpip install win-unicode-console
T:\> py -mrun your_script.py

Python 3.4, 유니 코드, 다른 언어 및 Windows와의 관계는 무엇입니까?를 참조하십시오 .

?이 상황에서 Python이 자동으로 인쇄하는 대신 실패 하게 만드는 방법 이 있습니까?

?귀하의 경우에 모든 불가피한 문자를 대체하는 것으로 충분하다면 envvar을 설정할 수 PYTHONIOENCODING있습니다 :

T:\> set PYTHONIOENCODING=:replace
T:\> python3 -c "print(u'[\N{EURO SIGN}]')"
[?]

Python 3.6 이상에서 envvar이 비어 있지 않은 문자열로 설정되어 PYTHONIOENCODING있지 않으면 대화식 콘솔 버퍼에 대해 envvar로 지정된 인코딩 이 무시됩니다 PYTHONLEGACYWINDOWSIOENCODING.


3
"Windows의 기본 콘솔은 이제 모든 유니 코드 문자를 허용합니다." 그러나 콘솔을 구성해야합니다. cmd 또는 python IDLE의 창 상단을 마우스 오른쪽 버튼으로 클릭하고 기본 / 글꼴에서 "Lucida 콘솔"을 선택하십시오. (일본어와 중국어는 나를 위해 일하지 않지만, 그것 없이는 살아남 아야합니다 ...)
JinSnow

2
@Guillaume : 대답은 "해당 글꼴이 구성되어있는 경우" Windows 콘솔에 대해 굵게 표시 됩니다. 이 답변은 IDLE을 언급하지는 않지만 글꼴을 구성 할 필요는 없습니다 (기본적으로 일본어 및 중국어 문자는 IDLE에서 잘 보입니다. print('\u4E01'), print('\u6b63')).
jfs

2
@Guillaume Windows 10에 언어 팩을 설치하면 중국어를 구할 수도 있습니다. 중국어를 지원하는 콘솔 글꼴이 추가되었습니다.
Mark Tolonen

28

코드 페이지를 65001로 변경하도록 제안하는 다른 그럴듯한 답변에도 불구하고 작동하지 않습니다 . (또한, 사용 인코딩 기본값을 변경하는 sys.setdefaultencoding것입니다 좋은 아이디어 없습니다 .)

작동하는 세부 사항 및 코드는 이 질문 을 참조하십시오 .


2
win-unicode-console코드를 기반으로하는 Python 패키지는 py -mrun your_script.pycommand를 사용하여 유니 코드를 직접 인쇄하는 경우 스크립트 수정을 피할 수 있습니다 .
jfs

12

나쁜 캐릭터를 안정적으로 표현하는 데 관심이 없다면 다음과 같은 것을 사용할 수 있습니다 (python> = 2.6, 3.x 포함).

from __future__ import print_function
import sys

def safeprint(s):
    try:
        print(s)
    except UnicodeEncodeError:
        if sys.version_info >= (3,):
            print(s.encode('utf8').decode(sys.stdout.encoding))
        else:
            print(s.encode('utf8'))

safeprint(u"\N{EM DASH}")

문자열의 잘못된 문자는 Windows 콘솔에서 인쇄 할 수있는 표현으로 변환됩니다.


.encode('utf8').decode(sys.stdout.encoding)글자 깨짐 예에 리드 u"\N{EM DASH}".encode('utf-8').decode('cp437')> -ΓÇö
JFS

간단하게 print(s.encode('utf-8'))컴파일러 오류를 방지 할 수있는 더 좋은 방법이 될 수있다. 대신 인쇄 할 수없는 문자에 대해 \ xNN 출력을 얻습니다. 진단 메시지에 충분했습니다.
코드 리드

4
이것은 엄청난입니다 화려 잘못. UTF-8로 인코딩 한 다음 8 비트 문자 세트로 디코딩하면 a) 종종 실패합니다. 모든 코드 페이지에 256 바이트 값 모두에 대한 문자가 있는 것은 아니며 b) 항상 데이터의 잘못된 해석으로 인해 Mojibake 엉망이 발생합니다.
Martijn Pieters

10

아래 코드는 Windows에서도 Python 출력을 UTF-8로 콘솔에 출력합니다.

콘솔은 Windows 7에서 문자를 잘 표시하지만 Windows XP에서는 문자를 잘 표시하지 않지만 적어도 작동하고 모든 플랫폼에서 스크립트의 일관된 출력을 얻는 것이 가장 중요합니다. 출력을 파일로 리디렉션 할 수 있습니다.

아래 코드는 Windows에서 Python 2.6으로 테스트되었습니다.


#!/usr/bin/python
# -*- coding: UTF-8 -*-

import codecs, sys

reload(sys)
sys.setdefaultencoding('utf-8')

print sys.getdefaultencoding()

if sys.platform == 'win32':
    try:
        import win32console 
    except:
        print "Python Win32 Extensions module is required.\n You can download it from https://sourceforge.net/projects/pywin32/ (x86 and x64 builds are available)\n"
        exit(-1)
    # win32console implementation  of SetConsoleCP does not return a value
    # CP_UTF8 = 65001
    win32console.SetConsoleCP(65001)
    if (win32console.GetConsoleCP() != 65001):
        raise Exception ("Cannot set console codepage to 65001 (UTF-8)")
    win32console.SetConsoleOutputCP(65001)
    if (win32console.GetConsoleOutputCP() != 65001):
        raise Exception ("Cannot set console output codepage to 65001 (UTF-8)")

#import sys, codecs
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
sys.stderr = codecs.getwriter('utf8')(sys.stderr)

print "This is an Е乂αmp١ȅ testing Unicode support using Arabic, Latin, Cyrillic, Greek, Hebrew and CJK code points.\n"

1
다른 콘솔을 사용하여 이것을 피할 수있는 방법이 있습니까?
endolith

@sorin : 왜 먼저 import win32console외부에서 try하고 나중에 조건부로 내부에서 try합니까? 그런 종류의 무의미하지 않습니까 (첫 번째 import)
0xC0000022L

가치가있는 것은 David-Sarah Hopwood가 제공하는 것입니다 (win32 확장 모듈 설치를 방해하지 않았기 때문에이 기능도 실행하지 못했습니다)
Jaykul

4
시스템 기본 인코딩을 변경하지 마십시오. 대신 유니 코드 값을 수정하십시오. 기본 인코딩을 변경하면 기본 동작 에 의존하는 라이브러리가 손상 될 수 있습니다 . 이 작업을 수행하기 전에 모듈을 강제로 다시로드해야하는 이유가 있습니다.
Martijn Pieters

7

파이썬 스크립트를 실행하기 전에 명령 행에이 코드를 입력하십시오.

chcp 65001 & set PYTHONIOENCODING=utf-8

5

지암 파올로로 돌라 (Giampaolo Rodolà)의 답변과 같이 더 더러운 : 나는 실제로 인코딩의 전체 주제를 이해하고 Windoze 콘솔에 적용하는 방법을 이해하는 데 오랜 시간 (곧)을 보내고 싶습니다.

현재 나는 단지 프로그램이 충돌하지 않을 것이라는 의미의 sthg를 원했다. 그리고 나는 너무 많은 이국적인 모듈을 가져 오는 것을 포함하지 않았다. 특히 Jython을 사용하고있다. 모듈은 실제로 사용할 수없는 것으로 판명되었습니다).

def pr(s):
    try:
        print(s)
    except UnicodeEncodeError:
        for c in s:
            try:
                print( c, end='')
            except UnicodeEncodeError:
                print( '?', end='')

NB "pr"은 "print"보다 타이프하기가 짧습니다 ( "safeprint"보다 타이핑하기에는 약간 짧습니다) ...!


영리하고 문제를 해결할 수있는 빠르고 더러운 방법입니다. 나는 이것이 간헐적 인 해결책에 훌륭하다고 생각합니다.
JFA

3

Python 2의 경우 다음을 시도하십시오.

print unicode(string, 'unicode-escape')

Python 3의 경우 다음을 시도하십시오.

import os
string = "002 Could've Would've Should've"
os.system('echo ' + string)

또는 win-unicode-console을 사용해보십시오.

pip install win-unicode-console
py -mrun your_script.py

2

TL; DR :

print(yourstring.encode('ascii','replace'));

나는 이것을 Twitch chat (IRC) 봇에서 일하면서 직접 만났습니다. (Python 2.7 최신)

응답하기 위해 채팅 메시지를 구문 분석하고 싶었습니다.

msg = s.recv(1024).decode("utf-8")

또한 사람이 읽을 수있는 형식으로 콘솔에 안전하게 인쇄하십시오.

print(msg.encode('ascii','replace'));

이것은 봇 던지기 UnicodeEncodeError: 'charmap'오류 문제를 수정하고 유니 코드 문자를로 바꿨습니다 ?.


2

문제의 원인은 Win 콘솔이 유니 코드를 기꺼이 받아들이지 않는 것이 아닙니다 (기본적으로 Win2k를 추측하기 때문에이 작업이 수행됨). 기본 시스템 인코딩입니다. 이 코드를 시도하고 그것이 무엇을 제공하는지 확인하십시오.

import sys
sys.getdefaultencoding()

그것이 ascii라고하면 원인이 있습니다. Win-c : \ python \ lib \ site-packages 또는 다음과 같은 내용으로 구성됩니다.

import sys
sys.setdefaultencoding('utf-8')

파일에서 인코딩을 지정하고 싶을 수도 있습니다.

# -*- coding: UTF-8 -*-
import sys,time

편집 : 더 많은 정보는 파이썬으로 뛰어 들기 훌륭한 책에서 찾을 수 있습니다.


2
sys에서 setdefaultencoding ()이 더 이상 없습니다 (모듈 문서에 따라 v2.0 기준).
존 케이지

지금 당장 증명할 수는 없지만 Windows에서 2.5 이후 버전 에서이 트릭을 사용했음을 알고 있습니다.
Bartosz Radaczyński 2009

6
"이 함수는 사이트 모듈 구현과 사이트 사용자 정의에 의해서만 사용됩니다. 사이트 모듈에서 사용하면 sys 모듈의 네임 스페이스에서 제거됩니다. "
Bartosz Radaczyński

4
실제로 Windows 콘솔을 utf-8로 설정할 수 있습니다. chcp 65001이라고 말하면 유니 코드가됩니다.
Bartosz Radaczyński

4
절대적으로 명확하게하기 위해 : 기본 인코딩을 변경 하는 것은 매우 나쁜 생각 입니다. 이것은 의사가 뼈를 올바르게 설정하지 않고 부러진 다리를 삐걱 거리고 아무 일도없는 것처럼 걷는 것과 유사합니다. 유니 코드 텍스트를 처리하는 모든 코드는 암시 적 인코딩 / 디코딩에 의존하지 않고 일관성있게 수행해야합니다.
Martijn Pieters

1

JF Sebastian의 답변과 관련이 있지만 더 직접적입니다.

콘솔 / 터미널로 인쇄 할 때이 문제가 발생하면 다음을 수행하십시오.

>set PYTHONIOENCODING=UTF-8

3
set PYTHONIOENCODING=UTF-8콘솔에서 cp437과 같은 다른 인코딩을 사용하면 mojibake 가 발생할 수 있습니다 . cp65001다양한 문제가 있습니다 . Windows 콘솔에 유니 코드를 인쇄하려면 현재 OEM 코드 페이지에 표시 할 수없는 문자를 ( 이러한 문자에서도 작동) 으로 바꾸는 데만 사용되는 내 대답 에서 WriteConsoleW()제안한대로 유니 코드 API를 사용해야합니다 ( ). 출력이 파일로 경로 재 지정된 경우 사용할 수 있습니다. PYTHONIOENCODING?WriteConsoleW()PYTHONIOENCODING
jfs

1

Python 3.6 windows7 : Python 콘솔 (python 로고가있는) 또는 Windows 콘솔 (cmd.exe로 작성 됨)을 사용하여 Python을 시작하는 여러 가지 방법이 있습니다.

Windows 콘솔에서 utf8 문자를 인쇄 할 수 없습니다. UTF-8 문자를 인쇄하면이 오류가 발생합니다.

OSError: [winError 87] The paraneter is incorrect 
Exception ignored in: (_io-TextIOwrapper name='(stdout)' mode='w' ' encoding='utf8') 
OSError: [WinError 87] The parameter is incorrect 

위의 답변을 이해하려고 시도하지 못했지만 설정 문제 일뿐이라는 것을 알았습니다. cmd 콘솔 창의 상단을 마우스 오른쪽 단추로 클릭 font하고 lucida 콘솔을 선택한 탭에서


0

제임스 술 락이 물었다.

파이썬이 자동으로 인쇄하도록 할 수있는 방법이 있습니까? 이 상황에서 실패하는 대신?

다른 솔루션은 Windows 환경을 수정하거나 Python의 print()기능을 대체 할 것을 권장 합니다. 아래의 답변은 Sulak의 요청 이행에 더 가깝습니다.

Windows 7에서 UnicodeEncodeError다음 을 throw하지 않고도 Python 3.5에서 유니 코드를 인쇄 할 수 있습니다 .

    대신 :     print(text)
    대체 :     print(str(text).encode('utf-8'))

파이썬은 예외를 던지는 대신, 인쇄 할 수없는 유니 코드 문자를 \ xNN 16 진 코드 로 표시합니다 .

  Halmalo n \ xe2 \ x80 \ x99 \ xc3 \ xa9tait plus qu \ xe2 \ x80 \ x99un 포인트 느와르

대신에

  할말로 네 타이트와 '포인트 누아르

물론, 후자는 ceteris paribus 가 바람직 하지만, 전자는 진단 메시지에 대해 완전히 정확합니다. 유니 코드는 리터럴 바이트 값으로 표시되기 때문에 인코딩 / 디코딩 문제를 진단하는 데 도움이 될 수도 있습니다.

참고 :str() 그렇지 않으면 encode()파이썬이 유니 코드 문자를 숫자의 튜플로 거부 하기 때문에 위 의 호출이 필요 합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.