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

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

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

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



답변

다음은 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를 기본값으로하는 코드가 중단 될 수 있습니다 (이 코드는 타사 코드 일 수 있으며 일반적으로 수정이 불가능하거나 위험합니다).


답변

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

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

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

export PYTHONIOENCODING=utf8


답변

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) 또는 둘 다 사용할 수 있습니다 !


답변

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

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


답변

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


답변

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

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이 유니 코드를 인식하는 경우), 유니 코드 문자열과 함께 사용될 때마다 “바이트”문자열을 명시 적으로 인코딩해야한다는 근본적인 문제가 해결되었습니다.


답변

첫째 : 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에서 유니 코드로 암시 적으로 변환됩니다 .