개발/Python

[파이썬] UnicodeDecodeError: 'utf8' codec can't decode byte 0x9c

MinorMan 2023. 1. 20. 12:54
반응형

<질문>

클라이언트에서 UTF-8 유효한 문자를 수신해야 하는 소켓 서버가 있습니다.

문제는 일부 클라이언트(주로 해커)가 모든 잘못된 종류의 데이터를 전송하고 있다는 것입니다.

정품 클라이언트를 쉽게 구별할 수 있지만 나중에 분석할 수 있도록 전송된 모든 데이터를 파일에 기록하고 있습니다.

가끔 이런 캐릭터가 나옵니다.œ그 원인UnicodeDecodeError오류.

해당 문자를 사용하거나 사용하지 않고 문자열 UTF-8을 만들 수 있어야 합니다.

업데이트:

내 특별한 경우 소켓 서비스는 MTA였으므로 다음과 같은 ASCII 명령만 수신할 것으로 예상합니다.

EHLO example.com
MAIL FROM: 
...

이 모든 것을 JSON으로 기록했습니다.

그런 다음 좋은 의도가 없는 일부 사람들이 모든 종류의 쓰레기를 보내기로 결정했습니다.

그렇기 때문에 내 특정한 경우에는 ASCII가 아닌 문자를 제거해도 괜찮습니다.


<답변1>

http://docs.python.org/howto/unicode.html#the-unicode-type

str = unicode(str, errors='replace')

또는

str = unicode(str, errors='ignore')

메모:이렇게 하면 문자 없이 문자열을 반환하는 해당 문자를 제거(무시)합니다.

나에게 이것은 내 응용 프로그램에서 허용하지 않는 비 ASCII 입력에 대한 보호로 사용하고 있기 때문에 이상적인 경우입니다.

대안:에서 open 메서드를 사용합니다.codecs파일에서 읽을 모듈:

import codecs
with codecs.open(file_name, 'r', encoding='utf-8',
                 errors='ignore') as fdata:

<답변2>

엔진을 C에서 Python으로 변경하면 저에게 트릭이 생겼습니다.

엔진은 C:

pd.read_csv(gdp_path, sep='\t', engine='c')

'utf-8' 코덱은 위치 18의 바이트 0x92를 디코딩할 수 없습니다: 유효하지 않은 시작 바이트

엔진은 Python입니다.

pd.read_csv(gdp_path, sep='\t', engine='python')

나를 위해 오류가 없습니다.


<답변3>

이러한 유형의 문제는 Python 3으로 이동한 지금 나에게 발생합니다. Python 2가 파일 인코딩과 관련된 문제를 단순히 스팀 롤링하고 있다는 것을 전혀 몰랐습니다.

차이점에 대한 좋은 설명과 위의 어느 것도 저에게 도움이 되지 않은 후 해결책을 찾는 방법을 찾았습니다.

http://python-notes.curiousefficiency.org/en/latest/python3/text_file_processing.html

요컨대, Python 3이 Python 2와 최대한 유사하게 작동하도록 하려면 다음을 사용하십시오.

with open(filename, encoding="latin-1") as datafile:
    # work on datafile here

그러나 기사를 읽으십시오. 모든 솔루션에 맞는 하나의 크기는 없습니다.


<답변4>

첫 번째, get_encoding_type을 사용하여 인코딩 파일 유형을 가져옵니다.

import os    
from chardet import detect

# get file encoding type
def get_encoding_type(file):
    with open(file, 'rb') as f:
        rawdata = f.read()
    return detect(rawdata)['encoding']

두 번째는 다음 유형의 파일을 여는 것입니다.

open(current_file, 'r', encoding = get_encoding_type, errors='ignore')

<답변5>

>>> '\x9c'.decode('cp1252')
u'\u0153'
>>> print '\x9c'.decode('cp1252')
œ

<답변6>

나는 같은 문제가 있었다UnicodeDecodeError이 줄로 해결했습니다. 최선의 방법인지는 모르겠지만 저에게는 효과적이었습니다.

str = str.decode('unicode_escape').encode('utf-8')

<답변7>

이 솔루션은 'ñ'과 같은 라틴 아메리카 악센트를 사용할 때 잘 작동합니다.

나는 단지 추가하여이 문제를 해결

df = pd.read_csv(fileName,encoding='latin1')

<답변8>

누군가 같은 문제가있는 경우를 대비하여. 나는 vim을 함께 사용하고 있습니다YouCompleteMe, 이 오류 메시지와 함께 ycmd를 시작하지 못했습니다. 내가 한 일은 다음과 같습니다.export LC_CTYPE="en_US.UTF-8", 문제가 사라졌습니다.


<답변9>

파일을 변경해야 하지만 파일의 인코딩을 모르는 경우 어떻게 해야 합니까? 인코딩이 ASCII 호환임을 알고 ASCII 부분만 검사하거나 수정하려는 경우 surrogateescape 오류 처리기로 파일을 열 수 있습니다.

with open(fname, 'r', encoding="ascii", errors="surrogateescape") as f:
    data = f.read()

<답변10>

순수한 7비트 ASCII를 허용하려는 경우 허용되지 않는 바이트를 버리십시오. 명시적으로 지정된 인코딩 없이는 어쨌든 원격 측에서 의도한 것을 추측할 수 있는 간단한 방법이 없습니다.

while bytes := socket.read_line_bytes():
    try:
        string = bytes.decode('us-ascii')
    except UnicodeDecodeError as exc:
        logger.warning('[%s] - rejected non-ASCII input %s' % (client, bytes.decode('us-ascii',  errors='backslashreplace'))
        socket.write(b'421 communication error - non-ASCII content rejected\r\n')
        continue
    ...

<답변11>

나는 같은 오류가 있었다.

나에게 Python은 바이트 "0x87"에 대해 불평했습니다. 나는 그것을 찾아 보았다https://bytetool.web.app/en/ascii/code/0x87/여기서 이 바이트는 코덱 Windows-1252에 속한다고 말했습니다.

그런 다음 Python 파일의 시작 부분에 이 줄만 추가했습니다.

#-*- encoding: Windows-1252 -*-"

그리고 모든 오류가 사라졌습니다. 이 줄을 추가하기 전에 Pandas에서 다음과 같이 파일을 가져오려고 했습니다.

Df = pd.read_csv(data, sep=",", engine='python', header=0, encoding='Windows-1252')

그러나 이것은 나에게 오류를 반환했습니다. 그래서 다시 이렇게 바꿨습니다.

Df = pd.read_csv(data, sep=",", engine='python', header=0)

<답변12>

  • django-storage는 django-storage == 1.8까지 텍스트 모드에서 암시적으로 바이트 파일 읽기를 지원합니다.
  • 에서 제거된 지원https://github.com/jschneier/django-storages/pull/657
  • 바이트 파일을 읽기 위한 바이너리 모드를 지정해야 합니다.
반응형