Python에서 stdout 파이핑 시 올바른 인코딩 설정
Python 프로그램의 출력을 파이핑할 때, Python 통역사는 인코딩에 대해 혼동을 느끼고 None으로 설정한다.이는 다음과 같은 프로그램을 의미한다.
# -*- coding: utf-8 -*-
print u"åäö"
정상적으로 실행될 경우 정상적으로 작동하지만 다음과 같이 실패함:
UnicodeEncodeError: 'ascII' 코덱이 위치 0에서 문자 u'\xa0'을 인코딩할 수 없음: 서수가 범위(128)에 없음
파이프 순서에 따라 사용할 때
배관할 때 이 작업을 수행하는 가장 좋은 방법은 무엇인가?셸/파일 시스템/사용 중인 모든 인코딩을 사용하라고만 말해도 될까?
지금까지 본 제안은 site.py을 직접 수정하거나, 이 해킹을 사용하여 디폴트인코딩을 하드코딩하는 것이다.
# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
print u"åäö"
파이프를 작동시키는 더 좋은 방법이 있을까?
Python이 당신의 터미널 응용 프로그램이 사용하고 있는 어떤 인코딩에도 출력을 인코딩하기 때문에 당신의 코드는 스크립트에서 실행될 때 작동한다.만약 당신이 파이프를 치고 있다면 당신은 그것을 직접 인코딩해야 한다.
경험의 법칙은 다음과 같다.항상 내부에서 유니코드를 사용하십시오.수신한 내용을 디코딩하고 전송한 내용을 인코딩하십시오.
# -*- coding: utf-8 -*-
print u"åäö".encode('utf-8')
또 다른 교훈적인 예로는 ISO-8859-1과 UTF-8 사이에서 변환하는 파이썬 프로그램이 있는데, 이 사이에 모든 것이 대문자로 만들어진다.
import sys
for line in sys.stdin:
# Decode what you receive:
line = line.decode('iso8859-1')
# Work with Unicode internally:
line = line.upper()
# Encode what you send:
line = line.encode('utf-8')
sys.stdout.write(line)
사용하는 일부 모듈과 라이브러리는 ASCII라는 사실에 의존할 수 있기 때문에 시스템 기본 인코딩을 설정하는 것은 좋지 않은 생각이다.하지 마세요.
첫째, 이 솔루션과 관련하여:
# -*- coding: utf-8 -*-
print u"åäö".encode('utf-8')
매번 주어진 인코딩으로 명시적으로 인쇄하는 것은 실용적이지 않다.그것은 반복적이고 오류가 발생하기 쉽다.
더 나은 해결책은 프로그램을 시작할 때 선택한 인코딩으로 인코딩하는 것이다.Python에서 찾은 해결책은 다음과 같다. sys.stdout.encoding을 선택하는 방법, 특히 "토카"의 코멘트:
import sys
import codecs
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
환경 변수 "PYthonIOENCODING"을 "utf_8"로 변경해 보십시오.나는 이 문제에 대한 나의 시련에 대해 한 페이지를 썼다.
블로그 포스트의 Tl;dr:
import sys, locale, os
print(sys.stdout.encoding)
print(sys.stdout.isatty())
print(locale.getpreferredencoding())
print(sys.getfilesystemencoding())
print(os.environ["PYTHONIOENCODING"])
print(chr(246), chr(9786), chr(9787))
너에게 주다
utf_8
False
ANSI_X3.4-1968
ascii
utf_8
ö ☺ ☻
export PYTHONIOENCODING=utf-8
그 일을 하기는 하지만, 그것을 비단뱀 그 자체에 맞출 수는 없다.
설정되지 않았는지 확인하고 통화 스크립트 전에 다음을 사용하여 설정하도록 사용자에게 지시하는 경우:
if __name__ == '__main__':
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)
코멘트에 회신할 수 있도록 업데이트: stdout에 파이핑할 때 문제가 발생함.나는 Fedora 25 Python 2.7.13에서 테스트를 했다.
python --version
Python 2.7.13
캣 b.py
#!/usr/bin/env python
#-*- coding: utf-8 -*-
import sys
print sys.stdout.encoding
./b.py 실행
UTF-8
running ./b.py | 더 적은 |
None
지난주에도 비슷한 문제가 있었어.내 IDE(PyCharm)에서는 쉽게 고칠 수 있었다.
내가 고친 건 바로 여기에 있다.
PyCharm 메뉴 모음부터 시작:파일 -> 설정...-> Editor -> File Encodings, 그 다음: "IDE Encoding", "Project Encoding" 및 "Properties 파일의 기본 인코딩" ALL to UTF-8로 설정, 그녀는 이제 매력적으로 작동한다.
이것이 도움이 되기를!
논쟁의 여지가 있는 Craig McQueen의 해답 버전.
import sys, codecs
class EncodedOut:
def __init__(self, enc):
self.enc = enc
self.stdout = sys.stdout
def __enter__(self):
if sys.stdout.encoding is None:
w = codecs.getwriter(self.enc)
sys.stdout = w(sys.stdout)
def __exit__(self, exc_ty, exc_val, tb):
sys.stdout = self.stdout
사용량:
with EncodedOut('utf-8'):
print u'ÅÄÖåäö'
다음 연락처로 자동화할 수 있다.
def __fix_io_encoding(last_resort_default='UTF-8'):
import sys
if [x for x in (sys.stdin,sys.stdout,sys.stderr) if x.encoding is None] :
import os
defEnc = None
if defEnc is None :
try:
import locale
defEnc = locale.getpreferredencoding()
except: pass
if defEnc is None :
try: defEnc = sys.getfilesystemencoding()
except: pass
if defEnc is None :
try: defEnc = sys.stdin.encoding
except: pass
if defEnc is None :
defEnc = last_resort_default
os.environ['PYTHONIOENCODING'] = os.environ.get("PYTHONIOENCODING",defEnc)
os.execvpe(sys.argv[0],sys.argv,os.environ)
__fix_io_encoding() ; del __fix_io_encoding
그렇다, 이 "setenv"가 실패한다면 여기서 무한 루프(infinite loop)를 얻을 수 있다.
나는 단지 내가 무슨 일이 일어나고 있는지 깨닫기 전에 오랜 시간을 실험에 소비해야 하는 것을 여기서 언급할 것이라고 생각했다.이것은 여기 있는 모든 사람들에게 너무나 명백해서 그들은 굳이 언급할 필요가 없었다.하지만 그들이 그랬다면 도움이 됐을 거야, 그러니 그 원칙에 따라...
NB: 난 Jython을 특별히 사용하고 있어, v 2.7, 그러니까 아마도 이것은 CPython에 적용되지 않을 수도 있어...
NB2: 여기 내 .py 파일의 처음 두 줄은 다음과 같다.
# -*- coding: utf-8 -*-
from __future__ import print_function
"%"(AKA "인터폴레이션 오퍼레이터") 문자열 구조 메커니즘도 추가 문제를 일으킨다."환경"의 기본 인코딩이 ASCII인 경우 다음과 같은 작업을 수행하려고 할 경우
print( "bonjour, %s" % "fréd" ) # Call this "print A"
Eclipse에서 뛰는 데는 어려움이 없을 것이다...Windows CLI(DOS 창)에서 인코딩이 코드 페이지 850(내 Windows 7 OS) 또는 이와 유사한 것으로, 유럽 악센트 문자를 최소한 처리할 수 있으므로 작동한다는 것을 알게 될 것이다.
print( u"bonjour, %s" % "fréd" ) # Call this "print B"
또한 효과가 있을 것이다.
OTOH가 CLI에서 파일로 직접 전송하는 경우 stdout 인코딩은 없음으로, 기본값은 ASCII(어쨌든 내 OS에서)로, 위의 인쇄물 중 하나를 처리할 수 없는 경우...(수정된 인코딩 오류).
그러면 당신은 당신의 stdout을
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
파일에 대한 CLI 파이프에서 실행해 보십시오.이상하게도 위의 A 인쇄물은...그러나 위의 B 인쇄는 인코딩 오류를 발생시킬 것이다!그러나 다음 사항은 정상 작동한다.
print( u"bonjour, " + "fréd" ) # Call this "print C"
내가 내린 결론은 (잠정적으로) "u" 접두사를 사용하여 유니코드 문자열로 지정된 문자열이 %-처리 메커니즘에 제출되면 stdout을 리디렉션으로 설정했는지 여부에 관계없이 기본 환경 인코딩을 사용하는 것으로 보인다는 것이다!
사람들이 이것을 어떻게 다루느냐 하는 것은 선택의 문제다.유니코드 전문가가 왜 이런 일이 일어나는지, 내가 어떤 식으로든 잘못 이해했는지, 이것에 대한 선호하는 해결책은 무엇인지, CPython에도 적용되는지, 파이톤 3에서 일어나는 일 등등을 말하는 것을 환영한다.
레거시 애플리케이션에서 우연히 이 문제를 접하게 되었는데, 인쇄된 것이 어디에 있는지 식별하기가 어려웠다.난 이 해킹을 도와줬어
# encoding_utf8.py
import codecs
import builtins
def print_utf8(text, **kwargs):
print(str(text).encode('utf-8'), **kwargs)
def print_utf8(fn):
def print_fn(*args, **kwargs):
return fn(str(*args).encode('utf-8'), **kwargs)
return print_fn
builtins.print = print_utf8(print)
내 대본 위에, 시험해봐.py:
import encoding_utf8
string = 'Axwell Λ Ingrosso'
print(string)
이렇게 하면 인코딩을 사용하기 위해 인쇄할 모든 호출이 변경되므로 콘솔에서 다음을 인쇄하십시오.
$ python test.py
b'Axwell \xce\x9b Ingrosso'
Windows에서, 나는 (Sublime Text와 같은) 편집기에서 Python 코드를 실행할 때 이 문제를 매우 자주 겪었지만, 명령줄에서 실행한다면 그렇지 않았다.
이 경우 편집자의 매개 변수를 확인하십시오.Sublime의 경우텍스트, 이 항목Python.sublime-build
해결:
{
"cmd": ["python", "-u", "$file"],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"selector": "source.python",
"encoding": "utf8",
"env": {"PYTHONIOENCODING": "utf-8", "LANG": "en_US.UTF-8"}
}
Python 3.7부터는 명령줄 옵션 -X utf8:를 사용하여 Python UTF-8 모드를 사용할 수 있다.
python -X utf8 testzh.py
스크립트 testzh.py에는 다음이 포함되어 있다.
print("Content-type: text/html; charset=UTF-8\n")
print("地球你好!")
Windows 10 Internet Service IIS를 CGI 스크립트 처리기로 설정하려면,
실행 파일을 다음과 같이 설정하십시오.
"C:\Program Files\Python39\python.exe" -X utf8 %s
이것은 Browser Microsoft에서 예상한 중국어 IDeogram에 대해 작동한다.이 스크린샷과 같은 에지:그렇지 않으면 오류가 발생한다.
https://docs.python.org/3/library/os.html#utf8-mode을 참조하십시오.
참조URL: https://stackoverflow.com/questions/492483/setting-the-correct-encoding-when-piping-stdout-in-python
'IT이야기' 카테고리의 다른 글
Python 수퍼()가 TypeError를 발생시킴 (0) | 2022.04.04 |
---|---|
반응 컨텍스트 및 후크 API의 효소 오류 (0) | 2022.04.04 |
Vuetify에서 v-card 구성 요소의 중앙에 콘텐츠를 맞추는 방법 (0) | 2022.04.04 |
효소, ReactTestUtils와 react-testing-library의 차이 (0) | 2022.04.04 |
대응 중인 확인란 목록을 확인/확인 해제하는 방법 (0) | 2022.04.04 |