파이썬의 기본 인코딩을 변경 하시겠습니까?


143

콘솔에서 응용 프로그램을 실행할 때 Python에서 많은 "인코딩 할 수 없음"및 "디코딩 할 수 없음"문제가 있습니다. 그러나 Eclipse PyDev IDE에서 기본 문자 인코딩은 UTF-8로 설정되어 있습니다.

기본 인코딩 설정을 검색했으며 사람들은 Python이 sys.setdefaultencoding시작시 함수를 삭제한다고 말하면서 사용할 수 없습니다.

그렇다면 가장 좋은 해결책은 무엇입니까?


1
블로그 게시물 Illusive setdefaultencoding을 참조하십시오 .
djc

3
The best solution is to learn to use encode and decode correctly instead of using hacks.이것은 자신의 인터페이스를 사용하여 / 일관되게 사용하는 것을 항상 기억 하면서 python2 에서 가능했습니다 . 필자의 경험에 따르면 python2와 python3으로 작업하려는 코드를 작성할 때 문제가 발생합니다.
Att Righ

답변:


159

다음은 setdefaultencoding()삭제 된 함수를 제공하는 간단한 방법 (해킹)입니다 sys.

import sys
# sys.setdefaultencoding() does not exist, here!
reload(sys)  # Reload does the trick!
sys.setdefaultencoding('UTF8')

(3.4 이상 파이썬 참고 : reload()에있는 importlib라이브러리입니다.)

그러나 이것은 안전한 일이 아닙니다 . 파이썬이 시작될 때 sys.setdefaultencoding()의도적으로 제거되었으므로 이것은 분명히 해킹 sys입니다. 이를 활성화 하고 기본 인코딩을 변경하면 ASCII를 기본값으로하는 코드가 중단 될 수 있습니다 (이 코드는 타사 코드 일 수 있으며 일반적으로 수정이 불가능하거나 위험합니다).


5
그 대답은 기존 응용 프로그램 (질문을 해석하는 한 가지 방법)을 실행하는 데 도움이되지 않기 때문에 응용 프로그램을 작성 / 유지 관리 할 때 잘못되어 라이브러리를 작성할 때 위험합니다. 올바른 방법은 설정하는 것입니다 LC_CTYPE(또는 응용 프로그램에서 올바르게 설정되어 있는지 확인하고 의미있는 오류 메시지와 함께 중단하십시오).
ibotty

@ibotty 나는이 답변이 해킹이며 그것을 사용하는 것이 위험하다는 것에 동의합니다. 그래도 ( "파이썬의 기본 인코딩 변경?") 질문에 대답합니다. 환경 변수 LC_CTYPE이 Python 인터프리터에 미치는 영향에 대한 참조가 있습니까?
Eric O Lebigot

글쎄, 언급하지 않았지만 처음에는 해킹입니다. 그 외에는 언급이없는 위험한 답변은 도움이되지 않습니다.
ibotty

1
@ EOL 당신이 맞아요. 그것은 선호하는 LC_CTYPE=C python -c 'import locale; print( locale.getpreferredencoding())'
인코딩에

1
@ user2394901 sys.setdefaultencoding () 사용은 항상 권장되지 않습니다 !! 그리고 py3k의 인코딩은 "utf-8"에 고정되어 있으며이를 변경하면 오류가 발생합니다.
Marlon Abeykoon 2016 년

70

스크립트 출력을 파이프 / 리디렉션하려고 할 때이 오류가 발생하는 경우

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)

콘솔에서 PYTHONIOENCODING을 내 보낸 다음 코드를 실행하십시오.

export PYTHONIOENCODING=utf8


3
이것은 나를 위해 유일한 차이를 만든 솔루션입니다. -로케일 설정이 깨진 데비안 7을 사용하고 있습니다. 감사.
Pryo

4
LC_CTYPE대신 합리적인 것으로 설정하십시오 . 다른 모든 프로그램도 만족합니다.
ibotty 2016 년

5
Python3의 더 큰 버그 PYTHONIOENCODING=utf8는 기본값이 아닙니다. 이로 인해 스크립트가 중단됩니다LC_ALL=C
Tino

Set LC_CTYPE to something sensible instead이것은 합리적인 제안입니다. 다른 사람의 시스템 에서만 작동 하는 코드를 배포하려고 할 때 제대로 작동하지 않습니다 .
Att Righ

데비안과 Redhat OS는 C.utf8로케일을 사용하여 보다 합리적인 C를 제공합니다. glibc 업스트림이 추가하는 중입니다. 로케일 설정을 존중하는 데 파이썬을 비난해서는 안됩니다.
Arthur2e5

52

A) sys.getdefaultencoding()출력 을 제어하려면 :

python -c 'import sys; print(sys.getdefaultencoding())'

ascii

그때

echo "import sys; sys.setdefaultencoding('utf-16-be')" > sitecustomize.py

PYTHONPATH=".:$PYTHONPATH" python -c 'import sys; print(sys.getdefaultencoding())'

utf-16-be

sitecustomize.py를에 더 높게 넣을 수 있습니다 PYTHONPATH.

또한 당신은 reload(sys).setdefaultencoding@EOL에 의해 시도 하고 싶을 수도 있습니다

B) 제어 stdin.encoding하고 stdout.encoding설정 하려면 PYTHONIOENCODING:

python -c 'import sys; print(sys.stdin.encoding, sys.stdout.encoding)'

ascii ascii

그때

PYTHONIOENCODING="utf-16-be" python -c 'import sys; 
print(sys.stdin.encoding, sys.stdout.encoding)'

utf-16-be utf-16-be

마지막으로 A) 또는 B) 또는 둘 다 사용할 수 있습니다 !


(python2 만) 분리하지만 흥미 전술 연장되어 from __future__ import unicode_literals보기 논의
lukmdo

17

PyDev 3.4.1 부터는 기본 인코딩이 더 이상 변경되지 않습니다. 자세한 내용은 이 티켓 을 참조하십시오.

이전 버전의 솔루션은 PyDev가 기본 인코딩으로 UTF-8과 함께 실행되지 않도록하는 것입니다. Eclipse에서 대화 상자 설정을 실행하십시오 (정확하게 기억하는 경우 "구성 실행"). 공통 탭에서 기본 인코딩을 선택할 수 있습니다. 이러한 오류를 '초기'(즉, PyDev 환경에서)하려는 경우 US-ASCII로 변경하십시오. 이 대안에 대한 원본 블로그 게시물 도 참조하십시오 .


1
고마워 크리스. 특히 위의 Mark T의 의견을 고려할 때 귀하의 답변이 나에게 가장 적합한 것 같습니다. 그리고 주로 Eclipse / PyDev 사용자가 아닌 누군가를 위해, 나는 그것을 스스로 알아 내지 못했을 것입니다.
Sean

전 세계적으로 (오히려 실행 구성 당 한 번 이상)이을 변경하려면,하지만 방법을 생각하지 않은 - 별도의 Q 요구했다 : stackoverflow.com/questions/9394277/...
팀 Diggins

13

python2 (및 python2 만 해당)와 관련하여 이전 답변 중 일부는 다음 해킹을 사용합니다.

import sys
reload(sys)  # Reload is a hack
sys.setdefaultencoding('UTF8')

사용하지 않는 것이 좋습니다 ( this 또는 this 확인 )

제 경우에는 부작용이 있습니다. ipython 노트북을 사용하고 있으며 코드를 실행하면 '인쇄'기능이 더 이상 작동하지 않습니다. 해결책이있을 것 같지만 여전히 해킹을 사용하는 것이 올바른 옵션이 아니라고 생각합니다.

많은 옵션을 시도한 후에 저에게 도움이 된 방법은에서 동일한 코드를 사용하는 sitecustomize.py 입니다. 해당 모듈을 평가 한 후 setdefaultencoding 함수가 sys에서 제거됩니다.

따라서 해결책은 /usr/lib/python2.7/sitecustomize.py코드 를 파일에 추가하는 것입니다 .

import sys
sys.setdefaultencoding('UTF8')

virtualenvwrapper를 사용할 때 편집하는 파일은 ~/.virtualenvs/venv-name/lib/python2.7/sitecustomize.py입니다.

파이썬 노트북 및 콘다와 함께 사용하면 ~/anaconda2/lib/python2.7/sitecustomize.py


8

그것에 대한 통찰력있는 블로그 게시물이 있습니다.

https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/를 참조 하십시오 .

나는 그 내용을 다음과 같이 표현한다.

문자열 인코딩과 관련하여 강력하게 입력되지 않은 Python 2에서는 다르게 인코딩 된 문자열에 대해 작업을 수행하고 성공할 수 있습니다. 예를 들어 다음이 반환 True됩니다.

u'Toshio' == 'Toshio'

로 인코딩 된 모든 (일반, 접두사가없는) 문자열에 대해 유지 되지만 sys.getdefaultencoding()기본값은로 설정 ascii되지만 다른 문자열은 아닙니다.

기본 인코딩은 시스템 전체에서 변경 site.py되었지만 다른 곳에서는 변경 되지 않았습니다. 사용자 모듈로 설정하기위한 해킹 (여기에도 제시)은 해킹이 아니라 해킹입니다.

파이썬 3은 시스템 인코딩을 기본값으로 utf-8로 변경했지만 (LC_CTYPE이 유니 코드를 인식하는 경우), 유니 코드 문자열과 함께 사용될 때마다 "바이트"문자열을 명시 적으로 인코딩해야한다는 근본적인 문제가 해결되었습니다.


4

첫째 : reload(sys)출력 터미널 스트림의 필요성과 관련하여 임의의 기본 인코딩을 설정하는 것은 나쁜 습관입니다. reloadsys.stdin / stdout 스트림, sys.excepthook 등 환경에 따라 배치 된 sys의 내용을 변경하는 경우가 종종 있습니다.

표준 출력에서 ​​인코딩 문제 해결

sys.stdout에서 print유니 코드 문자열과 ASCII 이외 str의 (예 : 리터럴) 인코딩 문제를 해결하는 데 가장 적합한 솔루션 은 다음과 같습니다. 필요에 따라 선택적으로 관용 :

  • sys.stdout.encoding입니다 None어떤 이유로, 또는 기존의 비, 또는 잘못 허위 또는 할 수있는 어떤 표준 출력 단자 또는 정말 스트리밍보다 "덜"다음 정확한 제공하기 위해 노력 .encoding속성을. 마지막으로 sys.stdout & sys.stderr번역 파일과 같은 객체 로 대체 합니다.

  • 터미널 / 스트림이 여전히 발생하는 모든 유니 코드 문자를 인코딩 할 수없는 경우와 그로 print인해 중단하고 싶지 않은 경우 변환하는 파일과 같은 객체에서 대체와 함께 인코딩 동작을 도입 할 수 있습니다.

예를 들면 다음과 같습니다.

#!/usr/bin/env python
# encoding: utf-8
import sys

class SmartStdout:
    def __init__(self, encoding=None, org_stdout=None):
        if org_stdout is None:
            org_stdout = getattr(sys.stdout, 'org_stdout', sys.stdout)
        self.org_stdout = org_stdout
        self.encoding = encoding or \
                        getattr(org_stdout, 'encoding', None) or 'utf-8'
    def write(self, s):
        self.org_stdout.write(s.encode(self.encoding, 'backslashreplace'))
    def __getattr__(self, name):
        return getattr(self.org_stdout, name)

if __name__ == '__main__':
    if sys.stdout.isatty():
        sys.stdout = sys.stderr = SmartStdout()

    us = u'aouäöüфżß²'
    print us
    sys.stdout.flush()

Python 2/2 + 3 코드에서 ASCII 이외의 일반 문자열 리터럴 사용

내가 생각하는 전역 기본 인코딩을 UTF-8로 변경하는 유일한 이유는 응용 프로그램 소스 코드 결정과 관련이 있으며 I / O 스트림 인코딩 문제 때문이 아닙니다. ASCII가 아닌 문자열 리터럴을 강제로 코드에 작성하지 않는 경우 항상 u'string'스타일 유니 코드 이스케이프를 사용합니다. ( anonbadger 에도 불구하고) 일관되게 수행 할 수 있습니다 ascii 또는 UTF-8 일반 문자열 리터럴을 일관되게 사용하는 Python 2 또는 Python 2 + 3 소스 코드 기반을 의 기사에 따르면). 유니 코드 변환 및 모듈 간 이동 또는 잠재적으로 표준 출력으로 이동합니다. 이를 위해서는 "# encoding: utf-8"또는 ascii (선언 없음). chr # 127 (오늘날 드문 경우) 이상의 ASCII 기본 인코딩 오류에 치명적으로 의존하는 라이브러리를 변경하거나 삭제하십시오.

그리고 SmartStdout위 의 구성표 외에도 응용 프로그램을 시작할 때 (또는 sitecustomize.py를 통해) 다음과 같이하십시오 reload(sys).

...
def set_defaultencoding_globally(encoding='utf-8'):
    assert sys.getdefaultencoding() in ('ascii', 'mbcs', encoding)
    import imp
    _sys_org = imp.load_dynamic('_sys_org', 'sys')
    _sys_org.setdefaultencoding(encoding)

if __name__ == '__main__':
    sys.stdout = sys.stderr = SmartStdout()
    set_defaultencoding_globally('utf-8') 
    s = 'aouäöüфżß²'
    print s

이런 식으로 문자열 리터럴과 대부분의 연산 (문자 반복 제외)은 파이썬 3 만있는 것처럼 유니 코드 변환을 생각하지 않고 편안하게 작동합니다. 물론 파일 I / O는 항상 Python3에서와 같이 인코딩과 관련하여 특별한주의가 필요합니다.

참고 : 그런 다음 일반 문자열 SmartStdout은 출력 스트림 인코딩 으로 변환되기 전에 utf-8에서 유니 코드로 암시 적으로 변환됩니다 .


4

다음은 python2python3 과 호환 되고 항상 utf8 출력 을 생성하는 코드를 생성하는 데 사용한 접근 방식 입니다. 다른 곳 에서이 답변을 찾았지만 출처를 기억할 수 없습니다.

이 방법은 파일sys.stdout 과 는 다른 것으로 대체 하지만 표준 라이브러리의 항목 만 사용하여 작동합니다. 이는 기본 라이브러리에 문제를 일으킬 수 있지만 프레임 워크를 통해 sys.stdout out을 사용하는 방법을 잘 제어하는 ​​간단한 경우에는 합리적인 접근 방법이 될 수 있습니다.

sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8')

3

이것은 나를 위해 문제를 해결했습니다.

import os
os.environ["PYTHONIOENCODING"] = "utf-8"

1

이것은 (1) Windows 플랫폼에서 (2) Python 2.7을 실행하고 (3) 멋진 소프트웨어로 인해 화가 났으며 (즉, 사용자가 작성하지 않았으므로 즉시 인코딩 / 디코딩 인쇄 후보가 아닙니다) 예를 들어 Stephan Boyer가 First Order Logic Prover의 교육적 프로 버의 출력에서 ​​사용하는 깔끔한 First Order Logic 기호는 IDLE 환경에서 "예쁜 유니 코드 문자"를 표시하지 않습니다 (Pythonwin은 유니 코드를 잘 인쇄 함) .

나는 sys reload를 강제하는 아이디어가 마음에 들지 않았고 시스템이 PYTHONIOENCODING (직접 Windows 환경 변수를 시도하고 sitepackages의 sitecustomize.py에있는 것과 같은) 환경 변수 설정과 협력 할 수 없었습니다. 라이너 = 'utf-8').

따라서 성공을 위해 기꺼이 해킹하려면 IDLE 디렉토리 (일반적으로 "C : \ Python27 \ Lib \ idlelib")로 이동하십시오. IOBinding.py 파일을 찾으십시오. 해당 파일의 사본을 만들어 다른 곳에 저장하면 선택시 원래 동작으로 되돌릴 수 있습니다. idlelib에서 파일을 편집기 (예 : IDLE)로 엽니 다. 이 코드 영역으로 이동하십시오.

# Encoding for file names
filesystemencoding = sys.getfilesystemencoding()

encoding = "ascii"
if sys.platform == 'win32':
    # On Windows, we could use "mbcs". However, to give the user
    # a portable encoding name, we need to find the code page 
    try:
        # --> 6/5/17 hack to force IDLE to display utf-8 rather than cp1252
        # --> encoding = locale.getdefaultlocale()[1]
        encoding = 'utf-8'
        codecs.lookup(encoding)
    except LookupError:
        pass

즉, 인코딩 변수를 locale.getdefaultlocale 과 같게 만드는 ' try ' 다음에 원래 코드 줄을 주석 처리하고 (원치 않는 cp1252를 제공하기 때문에) 대신 'utf-8로 강제 실행하십시오. '( 표시된대로 ' encoding = 'utf-8 ' 행을 추가하여 ).

필자는 이것이 파일 이름 등에 사용되는 인코딩 (이전의 파일 시스템 인코딩에서 얻은)이 아닌 IDLE 표시에 stdout에만 영향을 미친다고 생각합니다. 나중에 IDLE에서 실행하는 다른 코드에 문제가있는 경우 IOBinding.py 파일을 수정되지 않은 원래 파일로 바꾸십시오.


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