programing

Python의 기본 인코딩을 변경하시겠습니까?

sourcejob 2023. 6. 18. 13:07
반응형

Python의 기본 인코딩을 변경하시겠습니까?

콘솔에서 응용 프로그램을 실행할 때 Python과 관련하여 "인코딩할 수 없음" 및 "인코딩할 수 없음" 문제가 많습니다.하지만 Eclipse PyDev IDE에서는 기본 문자 인코딩이 UTF-8로 설정되어 있고, 저는 괜찮습니다.

인코딩 사람들이 .sys.setdefaultencoding시작 시 기능을 사용할 수 없습니다.

그렇다면 이를 위한 최선의 해결책은 무엇일까요?

다음은 더 간단한 방법(해킹)입니다.setdefaultencoding()에서 sys:

import sys
# sys.setdefaultencoding() does not exist, here!
reload(sys)  # Reload does the trick!
sys.setdefaultencoding('UTF8')

3: (Python 3.4+의 경우:reload()에 있습니다.importlib라이브러리).

하지만 이것은 안전하지 않습니다: 이것은 분명히 해킹입니다, 왜냐하면.sys.setdefaultencoding()에서 됩니다.sysPython이 시작될 때.이를 다시 활성화하고 기본 인코딩을 변경하면 ASCII를 기본으로 하는 코드가 끊어질있습니다(이 코드는 타사 코드일 수 있으므로 일반적으로 수정이 불가능하거나 위험합니다).

PS: 이 해킹은 더 이상 Python 3.9에서 작동하지 않는 것 같습니다.

스크립트의 출력을 파이프/재연결하려고 할 때 이 오류가 발생하는 경우

UnicodeError: 'asci' 코덱이 0-5 위치의 문자를 인코딩할 수 없음: 서수가 범위에 없음(128)

그냥 내보내기PYTHONIOENCODING콘솔에서 코드를 실행합니다.

export PYTHONIOENCODING=utf8

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

사이트를 사용자 지정할 수 있습니다. 높은 곳에 있는PYTHONPATH.

또한 @EOL로 시도해 보는 것도 좋습니다.

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부터는 기본 인코딩이 더 이상 변경되지 않습니다.자세한 내용은 이 티켓을 참조하십시오.

이전 버전에서는 UTF-8을 기본 인코딩으로 사용하여 PyDev가 실행되지 않도록 하는 것이 해결책입니다.Eclipse에서 대화 상자 설정 실행("실행 구성"). 공통 탭에서 기본 인코딩을 선택할 수 있습니다.이러한 오류를 '조기'(즉, PyDev 환경에서) 발생시키려면 US-ASCII로 변경합니다.또한 이 해결 방법에 대한 원본 블로그 게시물을 참조하십시오.

python2(및 python2만 해당)와 관련하여 이전 답변 중 일부는 다음과 같은 해킹에 의존합니다.

import sys
reload(sys)  # Reload is a hack
sys.setdefaultencoding('UTF8')

사용을 권장하지 않습니다(이것 또는 이것을 확인하십시오)

제 경우에는 부작용이 있습니다.ipython 노트북을 사용하고 있는데, 일단 코드를 실행하면 '인쇄' 기능이 더 이상 작동하지 않습니다.해결책이 있을 거라고 생각하지만 그래도 해킹을 사용하는 것은 올바른 선택이 되어서는 안 된다고 생각합니다.

여러 가지 옵션을 사용해 본 결과, 가 사용할 수 있었던 것은 해당 코드가 있어야 하는 에서 동일한 코드를 사용하는 것이었습니다.해당 모듈을 평가한 후 setdefault 인코딩 기능이 sys에서 제거됩니다.

은 파일에 입니다./usr/lib/python2.7/sitecustomize.py코드:

import sys
sys.setdefaultencoding('UTF8')

를 할 때 은 virtualenwrapper입니다.~/.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하지만 다른 곳은 아닙니다.사용자 모듈에서 이를 설정하기 위한 해킹(여기서도 제시됨)은 솔루션이 아니라 해킹이었습니다.

Python 3은 시스템 인코딩을 기본값인 utf-8(LC_CTYPE이 유니코드 인식일 때)로 변경했지만 유니코드 문자열과 함께 사용될 때마다 "바이트" 문자열을 명시적으로 인코딩해야 하는 요구 사항으로 인해 근본적인 문제가 해결되었습니다.

번째: 첫번째:reload(sys)출력 단자 스트림의 필요성에 따라 임의의 기본 인코딩을 설정하는 것은 좋지 않은 관행입니다. reloadsys. 스트림 sys.등의 stdin/stdout 파일, sys.tvpthook 파일과 변경합니다.

stdout에서 인코딩 문제 해결

인코문제의 하기 위해 가 알고 .print'ing 유니코드 문자열 및 그 이상의 문자열strsys.stdout의 sys.stdout): .stdout.stdout)에 대해 기능적이고 sys.과 유사한 개체 필요에 따라 기능하고 선택적으로 허용 가능한 sys.stdout(파일과 유사한 개체)을 처리합니다.

  • sys.stdout.encoding이라None보다 없거나 더한 어이로, 또존지않나거하잘, 나서거거터적이나미널스트이림제실로할못다니합력있떤고려노경우하공수는것보제을것정한은확다이유해짓재는▁a▁for▁then▁provide▁to적d▁correct다니합력"고려노하▁or공제,▁orless▁try을▁what▁"것d▁really한확어▁some▁than▁or▁the정▁non▁reason,,▁or▁terminal▁of떤,▁false▁st▁stream▁is▁erroneously우.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'스타일 유니코드 이스케이프 중입니다.이는 ASCII 또는 UTF-8 일반 문자열 리터럴을 일관되게 사용하는 Python 2 또는 Python 2 + 3 소스 코드 기반을 처리함으로써 (비배저의 기사가 언급하고 있음에도 불구하고) 상당히 일관적으로 수행될 수 있습니다.그것을 위해, "를 선호합니다.# encoding: utf-8또는 ascii(선언 없음).chr #127(현재는 거의 없음)을 초과하는 ASCII 기본 인코딩 오류에 치명적으로 의존하는 라이브러리를 변경하거나 삭제합니다.

그리고 애플리케이션 시작 시(또는 사이트 사용자 지정을 통해) 이와 같은 작업을 수행합니다.py) 에 더하여SmartStdout-를하지 않고 - 를 사용하는 방식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

이러한 방식으로 문자열 리터럴과 대부분의 작업(문자 반복 제외)은 Python3만 있는 것처럼 유니코드 변환에 대해 생각하지 않고 편하게 작동합니다.물론 파일 I/O는 Python3에서와 마찬가지로 인코딩과 관련하여 항상 특별한 주의가 필요합니다.

으로 변환됩니다.SmartStdout출력 스트림 인코딩으로 변환되기 전에.

다음은 python2python3 모두와 호환되며 항상 utf8 출력을 생성하는 코드를 생성하기 위해 사용한 접근 방식입니다.다른 곳에서 이 답을 찾았는데 출처가 기억이 안 나요.

이 접근 방식은 다음을 대체하여 작동합니다.sys.stdout파일과 유사하지는 않지만 표준 라이브러리의 항목만 사용합니다.이것은 기본 라이브러리에 문제를 일으킬 수 있지만, sys.stdout이 프레임워크를 통해 어떻게 사용되는지 잘 제어할 수 있는 간단한 경우에는 합리적인 접근 방식이 될 수 있습니다.

sys.stdout = io.open(sys.stdout.fileno(), 'w', encoding='utf8')

이것은 (1) Python 2.7을 실행하는 (2) Windows 플랫폼에서 (3) 좋은 소프트웨어(즉, 인코딩/디코드 인쇄 기동 후보가 아닌)가 IDLE 환경에서 "예쁜 유니코드 문자"를 표시하지 않기 때문에 짜증이 난 사람이라면 누구나 쉽게 해킹할 수 있습니다(Pythonwin prints fine).Stephan Boyer가 First Order Logic Prove에서 그의 교육학적 속담의 출력에 사용하는 깔끔한 First Order Logic 기호

저는 시스템을 강제로 다시 로드하는 아이디어가 마음에 들지 않았고 시스템이 PYONTIOENCODING(직접적인 Windows 환경 변수를 포함하고 단일 라이너 = 'utf-8'로 사이트에 있는 sitecustomize.py 에 삭제)과 같은 환경 변수 설정에 협력하도록 할 수 없었습니다.

따라서 성공으로 가는 길을 해킹할 의향이 있다면 IDLE 디렉토리로 이동하십시오. 일반적으로 "C:\Python27\Lib\idlelib" 파일 IOBinding.py 을 찾습니다.선택할 때 원래 동작으로 되돌릴 수 있도록 해당 파일의 복사본을 만들어 다른 곳에 저장합니다.편집기(예: IDLE)를 사용하여 idlelib에서 파일을 엽니다.다음 코드 영역으로 이동합니다.

# Encoding for file names
filesystemencoding = sys.getfilesystemencoding()

encoding = "ascii"
if sys.platform == 'win32':
    # On Windows, we could use "mbcs". However, to give the user
    # a portable encoding name, we need to find the code page 
    try:
        # --> 6/5/17 hack to force IDLE to display utf-8 rather than cp1252
        # --> encoding = locale.getdefaultlocale()[1]
        encoding = 'utf-8'
        codecs.lookup(encoding)
    except LookupError:
        pass

즉, 인코딩 변수를 locale.getdefaultlocale과 동일하게 만든 'try' 뒤에 있는 원래 코드 행을 주석 처리하고 대신 'utf-8'로 강제합니다(표시된 처럼 'cp1252가 제공되기 때문입니다).

이것은 IDLE 디스플레이에서 stdout에만 영향을 미치고 파일 이름 등에 사용되는 인코딩에는 영향을 미치지 않는다고 생각합니다(이전의 파일 시스템 인코딩에서 얻음).나중에 IDLE에서 실행하는 다른 코드에 문제가 있으면 IOBinding.py 파일을 수정되지 않은 원래 파일로 교체하십시오.

전체 운영 체제의 인코딩을 변경할 수 있습니다.Ubuntu에서 이 작업을 수행할 수 있습니다.

sudo apt install locales 
sudo locale-gen en_US en_US.UTF-8    
sudo dpkg-reconfigure locales

이것으로 저는 그 문제를 해결했습니다.

import os
os.environ["PYTHONIOENCODING"] = "utf-8"

합니다.UTF-8 »: Ubuntu에서/etc/default/locale설정:

LANG=en_US.UTF-8
LANGUAGE=en_US.UTF-8
LC_ALL=en_US.UTF-8

만약 당신이 안정적인 것만 원한다면요.UTF-8read/write모든 곳에서 동일한 선언 없이, 여기 두 가지 솔루션이 있습니다.

»io런타임 시 모듈(사용자가 위험을 감수하고 운영 중단)

import pathlib as pathlib
import tempfile

import chardet


def patchIOWithUtf8Default():
    import builtins
    import importlib.util
    import sys
    spec = importlib.util.find_spec("io")
    module = importlib.util.module_from_spec(spec)
    exec(compile(spec.loader.get_source(spec.name) + """
    def open(*args, **kwargs):
        args = list(args)
        mode = kwargs.get('mode', (args + [''])[1])
        if (len(args) < 4 and 'b' not in mode) or 'encoding' in kwargs:
            kwargs['encoding'] = 'utf8'
        elif len(args) >= 4 and args[3] is None:
            args[3] = 'utf8'
        return _io.open(*args, **kwargs)
    """, module.__spec__.origin, "exec"), module.__dict__)
    sys.modules[module.__name__] = module
    builtins.open = __import__("io").open
    importlib.reload(importlib.import_module("pathlib"))


def main():
    patchIOWithUtf8Default()
    filename = tempfile.mktemp()
    text = "Common\n常\nSense\n识\n天地玄黄"
    print("Original text:", repr(text))
    pathlib.Path(filename).write_text(text)
    encoding = chardet.detect(open(filename, mode="rb").read())["encoding"]
    print("Written encoding by pathlib:", encoding)
    print("Written text by pathlib:", repr(open(filename, newline="", encoding=encoding).read()))


if __name__ == '__main__':
    main()

샘플 출력:

Original text: 'Common\n常\nSense\n识\n天地玄黄'
Written encoding by pathlib: utf-8
Written text by pathlib: 'Common\r\n常\r\nSense\r\n识\r\n天地玄黄'

3번째 라이브러리를 pathlib 래퍼로 사용

https://github.com/baijifeilong/IceSpringPathLib

pip install IceSpringPathLib

import pathlib
import tempfile

import chardet

import IceSpringPathLib

tempfile.mktemp()
filename = tempfile.mktemp()
text = "Common\n常\nSense\n识\n天地玄黄"
print("Original text:", repr(text))

pathlib.Path(filename).write_text(text)
encoding = chardet.detect(open(filename, mode="rb").read())["encoding"]
print("\nWritten text by pathlib:", repr(open(filename, newline="", encoding=encoding).read()))
print("Written encoding by pathlib:", encoding)

IceSpringPathLib.Path(filename).write_text(text)
encoding = chardet.detect(open(filename, mode="rb").read())["encoding"]
print("\nWritten text by IceSpringPathLib:", repr(open(filename, newline="", encoding=encoding).read()))
print("Written encoding by IceSpringPathLib:", encoding)

샘플 출력:

Original text: 'Common\n常\nSense\n识\n天地玄黄'

Written text by pathlib: 'Common\r\n常\r\nSense\r\n识\r\n天地玄黄'
Written encoding by pathlib: GB2312

Written text by IceSpringPathLib: 'Common\n常\nSense\n识\n天地玄黄'
Written encoding by IceSpringPathLib: utf-8

Windows 설정 환경 변수 PYTHONUTF8=1

언급URL : https://stackoverflow.com/questions/2276200/changing-default-encoding-of-python

반응형