Program Tip

Python : ISO-8859-1 / latin1에서 UTF-8로 변환

programtip 2020. 10. 8. 18:50
반응형

Python : ISO-8859-1 / latin1에서 UTF-8로 변환


이메일 모듈을 사용하여 Quoted-printable에서 ISO-8859-1로 디코딩 된이 문자열이 있습니다. 이것은 "Äpple"(스웨덴어로 Apple)에 해당하는 "\ xC4pple"과 같은 문자열을 제공합니다. 그러나 해당 문자열을 UTF-8로 변환 할 수 없습니다.

>>> apple = "\xC4pple"
>>> apple
'\xc4pple'
>>> apple.encode("UTF-8")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0: ordinal not in     range(128)

어떻게해야합니까?


먼저 디코딩 한 다음 인코딩을 시도하십시오.

apple.decode('iso-8859-1').encode('utf8')

이것은 일반적인 문제이므로 비교적 철저한 그림이 있습니다.

유니 코드가 아닌 문자열 (예 : u접두사가 없는 문자열 u'\xc4pple')의 경우 네이티브 인코딩 ( iso8859-1/ latin1, 수수께끼sys.setdefaultencoding 함수로 수정 하지 않은 경우) 에서로 디코딩 unicode한 다음 원하는 문자를 표시 할 수있는 문자 집합으로 인코딩해야합니다.이 경우에는 I 추천 UTF-8합니다.

첫째, 다음은 Python 2.7 문자열 및 유니 코드의 패턴을 밝히는 데 도움이되는 편리한 유틸리티 함수입니다.

>>> def tell_me_about(s): return (type(s), s)

일반 문자열

>>> v = "\xC4pple" # iso-8859-1 aka latin1 encoded string

>>> tell_me_about(v)
(<type 'str'>, '\xc4pple')

>>> v
'\xc4pple'        # representation in memory

>>> print v
?pple             # map the iso-8859-1 in-memory to iso-8859-1 chars
                  # note that '\xc4' has no representation in iso-8859-1, 
                  # so is printed as "?".

iso8859-1 문자열 디코딩-일반 문자열을 유니 코드로 변환

>>> uv = v.decode("iso-8859-1")
>>> uv
u'\xc4pple'       # decoding iso-8859-1 becomes unicode, in memory

>>> tell_me_about(uv)
(<type 'unicode'>, u'\xc4pple')

>>> print v.decode("iso-8859-1")
Äpple             # convert unicode to the default character set
                  # (utf-8, based on sys.stdout.encoding)

>>> v.decode('iso-8859-1') == u'\xc4pple'
True              # one could have just used a unicode representation 
                  # from the start

더 많은 그림 — "Ä"

>>> u"Ä" == u"\xc4"
True              # the native unicode char and escaped versions are the same

>>> "Ä" == u"\xc4"  
False             # the native unicode char is '\xc3\x84' in latin1

>>> "Ä".decode('utf8') == u"\xc4"
True              # one can decode the string to get unicode

>>> "Ä" == "\xc4"
False             # the native character and the escaped string are
                  # of course not equal ('\xc3\x84' != '\xc4').

UTF로 인코딩

>>> u8 = v.decode("iso-8859-1").encode("utf-8")
>>> u8
'\xc3\x84pple'    # convert iso-8859-1 to unicode to utf-8

>>> tell_me_about(u8)
(<type 'str'>, '\xc3\x84pple')

>>> u16 = v.decode('iso-8859-1').encode('utf-16')
>>> tell_me_about(u16)
(<type 'str'>, '\xff\xfe\xc4\x00p\x00p\x00l\x00e\x00')

>>> tell_me_about(u8.decode('utf8'))
(<type 'unicode'>, u'\xc4pple')

>>> tell_me_about(u16.decode('utf16'))
(<type 'unicode'>, u'\xc4pple')

유니 코드와 UTF 및 latin1 간의 관계

>>> print u8
Äpple             # printing utf-8 - because of the encoding we now know
                  # how to print the characters

>>> print u8.decode('utf-8') # printing unicode
Äpple

>>> print u16     # printing 'bytes' of u16
���pple

>>> print u16.decode('utf16')
Äpple             # printing unicode

>>> v == u8
False             # v is a iso8859-1 string; u8 is a utf-8 string

>>> v.decode('iso8859-1') == u8
False             # v.decode(...) returns unicode

>>> u8.decode('utf-8') == v.decode('latin1') == u16.decode('utf-16')
True              # all decode to the same unicode memory representation
                  # (latin1 is iso-8859-1)

유니 코드 예외

 >>> u8.encode('iso8859-1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0:
  ordinal not in range(128)

>>> u16.encode('iso8859-1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0:
  ordinal not in range(128)

>>> v.encode('iso8859-1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0:
  ordinal not in range(128)

특정 인코딩 (latin-1, utf8, utf16)을 유니 코드로 변환하여 이러한 문제를 해결할 수 u8.decode('utf8').encode('latin1')있습니다.

따라서 아마도 다음과 같은 원칙과 일반화를 그릴 수 있습니다.

  • 유형 str은 Latin-1, UTF-8 및 UTF-16과 같은 여러 인코딩 중 하나를 가질 수있는 바이트 세트입니다.
  • 유형 unicode은 임의의 수의 인코딩, 가장 일반적으로 UTF-8 및 latin-1 (iso8859-1)로 변환 할 수있는 바이트 세트입니다.
  • the print command has its own logic for encoding, set to sys.stdout.encoding and defaulting to UTF-8
  • One must decode a str to unicode before converting to another encoding.

Of course, all of this changes in Python 3.x.

Hope that is illuminating.

Further reading

And the very illustrative rants by Armin Ronacher:


For Python 3:

bytes(apple,'iso-8859-1').decode('utf-8')

I used this for a text incorrectly encoded as iso-8859-1 (showing words like VeÅ\x99ejné) instead of utf-8. This code produces correct version Veřejné.


Decode to Unicode, encode the results to UTF8.

apple.decode('latin1').encode('utf8')

concept = concept.encode('ascii', 'ignore') 
concept = MySQLdb.escape_string(concept.decode('latin1').encode('utf8').rstrip())

I do this, I am not sure if that is a good approach but it works everytime !!

참고URL : https://stackoverflow.com/questions/6539881/python-converting-from-iso-8859-1-latin1-to-utf-8

반응형