[python] py 스크립트에서 sys.setdefaultencoding (“utf-8”)을 사용해서는 안되는 이유는 무엇입니까?

스크립트 상단에 이것을 사용하는 파이 스크립트는 거의 없습니다. 어떤 경우에 사용해야합니까?

import sys
reload(sys)
sys.setdefaultencoding("utf-8")



답변

설명서에 따르면 : 기본 ASCII에서 UTF-8과 같은 다른 인코딩으로 전환 할 수 있습니다. UTF-8은 문자열 버퍼를 유니 코드로 디코딩해야 할 때마다 Python 런타임에서 사용합니다.

이 함수는 Python이 환경을 스캔 할 때 Python 시작시에만 사용할 수 있습니다. 시스템 전체 모듈에서 호출해야합니다. sitecustomize.py이 모듈을 평가 한 후에는 setdefaultencoding()함수가 sys모듈 에서 제거됩니다 .

실제로 그것을 사용하는 유일한 방법은 속성을 다시 가져 오는 재로드 해킹입니다.

또한, 사용 sys.setdefaultencoding()은 항상 권장 되지 않았으며 py3k에서 no-op가되었습니다. py3k의 인코딩은 “utf-8″에 고정되어 있으며이를 변경하면 오류가 발생합니다.

나는 읽는 것에 대한 몇 가지 조언을 제안한다.


답변

tl; dr

대답은 결코 아니다 ! (내가하는 일을 정말로 모른다면)

인코딩 / 디코딩에 대한 적절한 이해를 통해 솔루션의 9/10 배를 해결할 수 있습니다.

1/10 명의 사용자가 로케일 또는 환경을 잘못 정의했으며 다음을 설정해야합니다.

PYTHONIOENCODING="UTF-8"  

환경에서 콘솔 인쇄 문제를 해결합니다.

무엇을합니까?

sys.setdefaultencoding("utf-8")(재사용을 피하기 위해 충돌) Python 2.x가 Unicode ()를 str ()로 변환해야하고 인코딩이 제공되지 않을 때마다 사용되는 기본 인코딩 / 디코딩을 변경합니다. 즉 :

str(u"\u20AC")
unicode("€")
"{}".format(u"\u20AC") 

Python 2.x에서 기본 인코딩은 ASCII로 설정되어 있으며 위 예제는 실패합니다.

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)

(내 콘솔은 UTF-8로 구성되어 "€" = '\xe2\x82\xac'있으므로 예외입니다 \xe2)

또는

UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)

sys.setdefaultencoding("utf-8")이것들은 나를 위해 작동 하지만 UTF-8을 사용하지 않는 사람들에게는 반드시 작동하지는 않습니다. ASCII의 기본값은 인코딩 가정이 코드로 구워지지 않도록합니다.

콘솔

sys.setdefaultencoding("utf-8")또한 sys.stdout.encoding콘솔에 문자를 인쇄 할 때 사용되는 것으로 나타나는 부작용이 있습니다. Python은 사용자 로캘 (Linux / OS X / Un * x) 또는 코드 페이지 (Windows)를 사용하여이를 설정합니다. 때때로 사용자의 로캘이 손상 PYTHONIOENCODING되어 콘솔 인코딩 만 수정하면 됩니다 .

예:

$ export LANG=en_GB.gibberish
$ python
>>> import sys
>>> sys.stdout.encoding
'ANSI_X3.4-1968'
>>> print u"\u20AC"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
>>> exit()

$ PYTHONIOENCODING=UTF-8 python
>>> import sys
>>> sys.stdout.encoding
'UTF-8'
>>> print u"\u20AC"
€

sys.setdefaultencoding ( “utf-8”) 의 문제점은 무엇입니까 ?

사람들은 기본 인코딩이 ASCII라는 것을 이해하면서 16 년 동안 Python 2.x에 대해 개발해 왔습니다. UnicodeError비 ASCII를 포함하는 것으로 확인 된 문자열에서 문자열을 유니 코드로 변환하는 것을 처리하기 위해 예외 처리 방법이 작성되었습니다.

에서 https://anonbadger.wordpress.com/2015/06/16/why-sys-setdefaultencoding-will-break-code/

def welcome_message(byte_string):
    try:
        return u"%s runs your business" % byte_string
    except UnicodeError:
        return u"%s runs your business" % unicode(byte_string,
            encoding=detect_encoding(byte_string))

print(welcome_message(u"Angstrom (Å®)".encode("latin-1"))

defaultencoding을 설정하기 전에이 코드는 ASCII 인코딩에서 “Å”을 디코딩 할 수 없었으며 예외 처리기를 입력하여 인코딩을 추측하고 올바르게 유니 코드로 바꿨습니다. 인쇄 : Angstrom (Å®)은 비즈니스를 운영합니다. defaultencoding을 utf-8로 설정하면 코드는 byte_string이 utf-8로 해석 될 수 있음을 발견하여 데이터를 엉망으로 만들고이를 대신 반환합니다. Angstrom (Ů)은 비즈니스를 운영합니다.

일정한 것을 변경하면 의존하는 모듈에 큰 영향을 미칩니다. 코드에서 들어오고 나가는 데이터를 수정하는 것이 좋습니다.

문제 예

다음 예제에서 기본 인코딩을 UTF-8로 설정하는 것이 근본 원인은 아니지만 문제가 어떻게 마스크되는지, 입력 인코딩이 변경 될 때 코드가 명백하지 않은 방식으로 중단되는 방법을 보여줍니다.
UnicodeDecodeError : ‘utf8’codec can 3131 위치에서 바이트 0x80을 디코딩하지 않습니다 : 유효하지 않은 시작 바이트


답변

#!/usr/bin/env python
#-*- coding: utf-8 -*-
u = u'moçambique'
print u.encode("utf-8")
print u

chmod +x test.py
./test.py
moçambique
moçambique

./test.py > output.txt
Traceback (most recent call last):
  File "./test.py", line 5, in <module>
    print u
UnicodeEncodeError: 'ascii' codec can't encode character
u'\xe7' in position 2: ordinal not in range(128)

쉘에서 작동하지만 sdtout으로 보내지 않으므로 stdout에 쓰는 것이 하나의 해결 방법입니다.

sys.stdout.encoding이 정의되지 않은 경우 또는 달리 말하면 stdout에 쓰려면 먼저 PYTHONIOENCODING = UTF-8 내보내기가 필요한 다른 방법을 사용했습니다.

import sys
if (sys.stdout.encoding is None):
    print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout."
    exit(1)

따라서 동일한 예제를 사용하십시오.

export PYTHONIOENCODING=UTF-8
./test.py > output.txt

작동합니다


답변

  • 첫 번째 위험은에 reload(sys)있습니다.

    모듈을 다시로드하면 실제로 런타임에 두 개의 모듈 사본이 제공됩니다. 이전 모듈은 다른 모든 것과 마찬가지로 Python 객체이며 참조가있는 한 살아 있습니다. 따라서 객체의 절반은 이전 모듈을 가리키고 절반은 새 모듈을 가리 킵니다. 변경하면 임의의 객체가 변경 사항을 볼 수 없을 때 변경 사항이 표시되지 않습니다.

    (This is IPython shell)
    
    In [1]: import sys
    
    In [2]: sys.stdout
    Out[2]: <colorama.ansitowin32.StreamWrapper at 0x3a2aac8>
    
    In [3]: reload(sys)
    <module 'sys' (built-in)>
    
    In [4]: sys.stdout
    Out[4]: <open file '<stdout>', mode 'w' at 0x00000000022E20C0>
    
    In [11]: import IPython.terminal
    
    In [14]: IPython.terminal.interactiveshell.sys.stdout
    Out[14]: <colorama.ansitowin32.StreamWrapper at 0x3a9aac8>
  • 지금, sys.setdefaultencoding() 적절한

    영향을 미치는 것은 암시 적 변환str<->unicode 입니다. 자, utf-8지구상에서 가장 안전한 인코딩 (ASCII 및 모든 버전과 역 호환 가능), 변환이 “작동합니다”, 무엇이 잘못 될 수 있습니까?

    뭐든지 요 그리고 그것은 위험입니다.

    • UnicodeError비 ASCII 입력에 대해 발생하거나 오류 처리기를 사용하여 코드 변환을 수행하는 일부 코드가있을 수 있으며 이로 인해 예기치 않은 결과가 발생합니다. 과 모든 코드는 기본 설정으로 테스트되었으므로 여기서 “지원되지 않는”영역을 엄격하게 따르고 아무도 코드의 작동 방식을 보증하지 않습니다.
    • Python 2에는 실제로 여러 개의 독립적 인 “기본 문자열 인코딩”이 있기 때문에 시스템의 모든 것이 UTF-8을 사용하지 않는 경우 트랜스 코딩에서 예기치 않거나 사용할 수없는 결과가 발생할 수 있습니다. . (프로그램은 고객의 장비에서 고객을 위해 작동해야 함을 기억하십시오.)
      • 다시, 최악의 상황은 당신이 알고하지 않습니다 변환이 암시하기 때문에 언제 어디에서 그런 일이 정말 모르겠어요 -. (Python Zen, koan 2 ahoy!) 코드가 한 시스템에서 작동하고 다른 시스템에서 작동하는 이유를 알 수 없습니다. (또는 아직은 IDE에서 작동하고 콘솔에서 작동하지 않습니다.)

답변