2010-12-07 4 views
35

Python 2에서 기본 출력 인코딩을 설정하는 것은 잘 알려진 관용구입니다.파이썬 3에서 sys.stdout 인코딩을 설정하는 방법?

sys.stdout = codecs.getwriter("utf-8")(sys.stdout) 

이 코드는 출력을 UTF-8로 인코딩하는 코덱 작성기에서 sys.stdout 객체를 래핑합니다.

sys.stdout = codecs.getwriter("utf-8")(sys.stdout) 
그러나 sys.stdout.write()str를 예상하지만 인코딩 결과는 bytes이므로 codecs이 인코딩 된 바이트를 원래 sys.stdout에 쓰려고 할 때 오류가 발생하므로이 기술은 Python 3에서 작동하지 않습니다.

파이썬 3에서 올바른 방법은 무엇입니까?

+0

2to3은 이와 같은 질문에 유용한 도구입니다. –

+0

@dan_waterworth : 이전에는 그렇게 생각하지 않았지만 지금은'2to3'을 시도했지만 주어진 코드에 대한 변경을 제안하지 않았습니다. –

+3

새 코드가 작동하지 않으면 버그로 추가하는 것이 좋습니다. –

답변

30

파이썬 3.1 sys.stdout에 대한 문서에서 메모와 함께, io.TextIOBase.detach()을 추가 :

표준 스트림은 기본적으로 텍스트 모드에 있습니다. 이진 데이터를 쓰거나 읽으려면 기본 이진 버퍼를 사용하십시오. 예를 들어 stdout에 바이트를 쓰려면 sys.stdout.buffer.write(b'abc')을 사용하십시오. io.TextIOBase.detach() 스트림을 사용하면 기본적으로 이진으로 만들 수 있습니다. 이 기능은 바이너리 stdinstdout 설정 : 따라서

def make_streams_binary(): 
    sys.stdin = sys.stdin.detach() 
    sys.stdout = sys.stdout.detach() 

, 늦은 파이썬 3.1에 해당하는 관용구 :

sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach()) 
+5

'PYTHONIOENCODING' 사용; 그렇지 않으면'io.TextIOWrapper'가 newline을 제대로 처리하기위한'codecs '보다 나은 대안이 될 수 있습니다. – jfs

+0

이것은'sys.stdout'의 동작을 완전히 바꿉니다. 'codecs.getwriter'에 의해 반환 된'StreamWriter'는 더 이상 라인 버퍼링을하지 않습니다. 예를 들어 – Sebastian

7

sys.stdout은 따라서 파이썬 3. 텍스트 모드에 유니 코드를 직접 작성하고 파이썬 2 용 관용구는 더 이상 필요하지 않습니다.

이 파이썬이 실패 할 경우 : 그러나

>>> import sys 
>>> sys.stdout.write(u"ûnicöde") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfb' in position 0: ordinal not in range(128) 

, 파이썬 3 단지 멋쟁이 작동합니다

파이썬이 stdouts 인코딩이 실제로 무엇인지 모르는 경우 지금
>>> import sys 
>>> sys.stdout.write("Ûnicöde") 
Ûnicöde7 

, 그것은 파이썬 빌드에서 다른 문제 일 가능성이 큽니다. 파이썬 2에서 기본 출력 인코딩을 설정

+2

내 컨텍스트는 파이썬 스크립트를 Apache에서 CGI로 실행하고 있는데, 기본 출력 인코딩은 내가 필요로하지 않습니다 (UTF- 8). 필자는 스크립트가 외부 설정 (예 : PYTHONIOENCODING과 같은 환경 변수)에 의존하기보다는 출력이 올바른 인코딩으로되어 있는지 확인하는 것이 좋습니다. –

+1

또 다른 증거는 프로세스 통신을 위해 stdout을 사용하는 것이 큰 실수라는 것입니다. 이 경우 CGI를 사용하는 것보다 선택의 여지가있을 수 있음을 알고 있습니다 만, 그건 당신 잘못이 아닙니다. :-) –

+0

파이썬 2에서는'sys.stdout'이 파이썬 2에서는 * 바이너리 * 파일이고 파이썬 3에서는 * 텍스트 * 파일이 사실이지만, 파이썬 2 예제는 유니 코드 문자열'u "ûnicöde" 'sys.stdout.write' 메쏘드에 암묵적으로 인코딩 된 것은 ASCII 범위를 벗어나는 문자들을 가지고 있습니다. 'LC_CTYPE','LANG' 또는'PYTHONIOENCODING' 환경 변수를 유니 코드 문자열의 모든 문자를 가진 인코딩으로 변경하면 에러가 발생하지 않아야합니다. (필자는 Python 2.7을 사용해 보았습니다.) – Maggyero

16

잘 알려진 관용구

에크입니다! Python 2에서 잘 알려진 관용구입니까? 그것은 나에게 위험한 실수처럼 보입니다.

stdout에 바이너리를 쓰려고하는 스크립트를 망칠 것입니다 (예를 들어 이미지를 반환하는 CGI 스크립트 인 경우 필요합니다). 바이트와 ​​문자는 아주 다른 동물입니다. char만을 취하는 것으로 바이트를 받아들이도록 (듯이) 지정되고있는 인터페이스를 monkey-patch하는 것은 좋은 생각이 아닙니다.

일반적으로 CGI와 HTTP는 바이트로 명시 적으로 작동합니다. sys.stdout에만 바이트를 보내야합니다. Python 3에서는 sys.stdout.buffer.write을 사용하여 바이트를 직접 전송한다는 의미입니다. charset 매개 변수와 일치하도록 페이지 컨텐츠를 인코딩하는 것은 애플리케이션의 상위 레벨에서 처리해야합니다 (바이너리가 아닌 텍스트 컨텐츠를 반환하는 경우). 이것은 또한 print이 더 이상 CGI에 적합하지 않음을 의미합니다.

(이 마침내 가능한입니다 PEP 3333 파이썬 3.2., wsgiref의 CGIHandler이 불가능 그런 식으로 CGI하는 WSGI를 배포하고, 최근까지 py3k 깨진 된 혼란에 추가합니다.)

+0

이 주석은 3.3 및 향후 3.4 Python 릴리스와 관련하여 업데이트되어야합니다. 고마워요 – soshial

18

I을 이 파이썬 후 다음 sys.stdout 교환 덜 문제가 -

이미 제안들에 대한 대안 솔루션 파이썬 내 사용을 위해, 시작 변수 전에 PYTHONIOENCODING 환경을 설정하는 것입니다

, 동일한 오류에 대한 해결책을 검색하는 동안이 스레드를 발견 초기화 됨 :

PYTHONIOENCODING=utf-8:surrogateescape python3 somescript.py 

파이썬 코드를 편집 할 필요가 없다는 장점이 있습니다. 의

default_out = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') 

을 (그리고이 나를 위해 잘 작동,

Exception ignored in: <_io.TextIOWrapper mode='w' encoding='UTF-8'> 
ValueError: underlying buffer has been detached 

을 대신 :

+0

엄청나게 많이 올리는 이유는 주로 PYTHONIOENCODING = utf-8이 수 시간 동안 검색을 한 후 내 문제를 해결했기 때문입니다. – theeggman85

5

그것이 종료 직전에 표준 출력을 닫습니다하려고 할 때 경고를 인쇄 할 인터프리터를 detach() 원인 사용 물론, 표준 출력 대신 default_out에 쓰십시오.)

15

다른 답변은 codecs이지만을 사용하는 것이 좋습니다저에게 적합합니다 :

import sys 
sys.stdout = open(sys.stdout.fileno(), mode='w', encoding='utf8', buffering=1) 
print("日本語") 
# Also works with other methods of writing to stdout: 
sys.stdout.write("日本語\n") 
sys.stdout.buffer.write("日本語\n".encode()) 

PYTHONIOENCODING="ascii"으로 실행해도 작동합니다.

관련 문제