IT이야기

왜 우리는 sys를 사용하지 말아야 하는가.py 스크립트에서 setdefaultencoding("utf-8")을 설정하시겠습니까?

cyworld 2022. 4. 6. 19:41
반응형

왜 우리는 sys를 사용하지 말아야 하는가.py 스크립트에서 setdefaultencoding("utf-8")을 설정하시겠습니까?

나는 대본 맨 위에서 이것을 사용하는 py 스크립트를 거의 본 적이 없다.어떤 경우에 그것을 사용해야 하는가?

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

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

이 기능은 Python이 환경을 스캔하는 Python 시작 시간에만 사용할 수 있다.시스템 전체에 걸친 모듈로 호출되어야 한다.sitecustomize.py 이 한 후 , , 이 을(를) 평가한다setdefaultencoding()기능이 에서 제거됨sys모듈

그것을 실제로 사용하는 유일한 방법은 속성을 다시 불러오는 재로드 해킹을 하는 것이다.

또한 의 사용은 금기시되어, py3k에서는 노op이 되었다.py3k의 인코딩은 "utf-8"에 유선 연결되며 이를 변경하면 오류가 발생한다.

나는 독서의 몇 가지 포인터를 제안한다.

tl;dr

정답은 절대 아니다!(unless you really know what you're doing)

9/10배는 인코딩/디코딩에 대한 적절한 이해로 해결할 수 있다.

1/10명의 사용자가 로케일 또는 환경이 잘못 정의되어 있으며 다음을 설정해야 함:

PYTHONIOENCODING="UTF-8"  

콘솔 인쇄 문제를 해결하기 위한 환경.

그게 무슨 소용이야?

sys.setdefaultencoding("utf-8") (재사용을 피하기 위해 검사) Python 2.x가 유니코드()를 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은 사용자의 로케일(리눅스/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에 대해 발전해 왔다. UnicodeErrorASCII가 아닌 문자열을 포함하는 것으로 확인된 문자열의 유니코드 변환을 처리하기 위해 예외 처리 방법이 작성되었다.

출처: 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"))

디폴트인코딩을 설정하기 전에 이 코드는 아스키 인코딩에서 "Ⅱ"를 디코딩할 수 없었으며, 그런 다음 예외 핸들러를 입력하여 인코딩을 추측하고 유니코드로 적절히 변환한다.인쇄 중:Angstrom(Angstrom, your®)이 비즈니스를 운영한다.일단 디폴트엔코딩을 utf-8로 설정하면, 이 코드는 byte_string이 utf-8로 해석될 수 있다는 것을 알게 될 것이고, 따라서 데이터가 엉망이 되고 대신 이를 반환하게 될 것이다.앙스트롬(Angstrom)이 비즈니스를 운영한다.

상수여야 할 것을 바꾸는 것은 당신이 의존하는 모듈에 극적인 영향을 줄 것이다.코드에 들어오고 나가는 데이터만 고치는 게 좋다.

예시 문제

디폴트인코딩을 UTF-8로 설정하는 것이 다음 예에서 근본 원인은 아니지만, 문제가 어떻게 마스킹되는지, 그리고 입력 인코딩이 변경될 때 코드는 모호하지 않은 방식으로 끊어지는지를 보여준다: 유니코드코드Error: 'utf8' 코덱은 위치 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)

shell works에, sdtout에 보내는 것은 not, 그래서 그것은 하나의 해결책이다, stdout에 쓰는 것.

나는 sys.stdout.encoding이 정의되어 있지 않으면 실행되지 않는 다른 접근법을 만들었고, 다른 말로 하면 stdout에 쓰기 위해 먼저 PYTINIOENCoding=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).

    모듈을 다시 로드하면 실제로 런타임에 모듈의 복사본이 두 개 제공된다.구 모듈은 다른 모든 것들과 마찬가지로 파이톤 물체로, 그것에 대한 참조가 있는 한 살아 있다.그래서, 절반의 물체는 오래된 모듈을 가리키고, 절반은 새로운 모듈을 가리킬 것이다.어떤 변화를 만들 때, 어떤 임의의 물체가 변화를 보지 못할 때, 당신은 그것이 오는 것을 결코 볼 수 없을 것이다.

    (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()본래의

    그게 영향을 미치는 건 암묵적 변환뿐이야utf-8지구상에서 가장 건전한 인코딩(ASCII와 모든 것이 역호환 가능), 변환은 이제 "그냥 작동한다"고, 무엇이 잘못될있는가?

    뭐, 아무거나.그리고 그것이 위험이다.

    • 에 의존하는 코드가 있을지도 모른다.UnicodeErrorASCII가 아닌 입력을 위해 던져지거나, 오류 처리기를 사용하여 트랜스코딩을 수행하게 되어, 이제 예상치 못한 결과가 발생한다.그리고 모든 코드가 기본 설정으로 테스트되기 때문에, 여기서는 엄격히 "지원되지 않는" 영역에 속하며, 아무도 그들의 코드가 어떻게 동작할지에 대한 보증을 주지 않는다.
    • 파이선 2는 실제로 여러 개의 독립적인"기본 문자열 인코딩"을 가지고 있기 때문에 시스템의 모든 것이 UTF-8을 사용하지 않는 경우 트랜스코딩은 예상치 못한 또는 사용할 수 없는 결과를 초래할 수 있다.(기억, 프로그램은 고객 장비에서 고객을 위해 작동해야 함)
      • 다시 말하지만, 가장 나쁜 것은 변환이 암묵적이기 때문, 언제 어디서 일어나는지 잘 모른다는 것이다. (피톤 젠, 코안 2 아호이!)당신은 당신의 코드가 왜 하나의 시스템에서 작동하고 다른 시스템에서 중단되는지 결코 알 수 없을 것이다. (또는 더 나은 것은 IDE에서 작동하고 콘솔에서 중단된다.)

참조URL: https://stackoverflow.com/questions/3828723/why-should-we-not-use-sys-setdefaultencodingutf-8-in-a-py-script

반응형