【问题标题】:How convert abitrary string into bytes without UnicodeEncodeError issue?如何在没有 UnicodeEncodeError 问题的情况下将任意字符串转换为字节?
【发布时间】:2017-11-02 04:12:48
【问题描述】:

我不应该期望这里有任何错误。我只想按字面意思获取字符串并将其转换为字节。我不想编码或解码任何东西。

我在这里举一个愚蠢的例子:

>>> astring
u'\xb0'

傻到让我头疼……

>>> bytes(astring)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xb0' in position...

一个可怕的技巧是这样做:

>>> bytes(repr(astring)[2:-1])
'\xb0'

另一个不好的解决方案是:

>>> bytes(astring.encode("utf-8"))
'\xc2\xb0'

这是一个糟糕的解决方案,因为我的字符串不是由两个字符组成的。这是错误的。

另一个糟糕的解决方案是:

>>> bytes(''.join(map(bytes, [chr(ord(c)) for c in astring])))
'\xb0'

我正在使用 Python 2.7

背景

我想比较数据库中编码未知且有时相互冲突的两列。我不在乎我的转储上的错误字符。我只是想让它看看它。

【问题讨论】:

  • 您应该始终提及您用于 Unicode 问题的 Python 版本。你是什​​么意思“把它翻译成它的字节”? Unicode 字符串是代码点序列,而不是字节序列。如果你想要字节,那么你需要执行编码。
  • 如果我将一个字符串加载到内存中,它就是一个原始二进制数据序列。无论内容如何,​​我都应该能够随时将其转储为字节。
  • 但是Unicode字符串不是字节串!当然,在硬件层面,一切都是字节(嗯,真的是机器字,但我们不要分心;)),但是将 Unicode 字符串视为字节字符串是没有用的。在 Python 3 中,字节和文本之间的区别更加清晰,而在 Python 2 中则不太清楚,这可能导致各种形式的混淆。
  • 怀疑您可以通过将 Unicode 数据编码为 Latin1 来获得所需的字节。 u'\xb0'.encode('latin1') 可以工作(在 Python 2 和 3 中),但我不能保证它会对 Unicode 字符串中可能存在的其他数据执行您想要的操作。

标签: python string python-2.7 unicode


【解决方案1】:

如果您的 Unicode 字符串保证只包含

r = range(256)
s = u''.join([unichr(i) for i in r])
print repr(s)

b = s.encode('latin1')
print repr(b)

a = [ord(c) for c in b]
print a == r

输出

u'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'
'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'
True

FWIW,这是等效的 Python 3 代码。

r = range(256)
s = u''.join([chr(i) for i in r])
print(repr(s))

b = s.encode('latin1')
print(repr(b))
print(list(b) == list(r))

输出

'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0¡¢£¤¥¦§¨©ª«¬\xad®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'
True

请注意,Python 3 Unicode repr 输出更加人性化。

【讨论】:

    【解决方案2】:

    您不能只“按字面意思理解字符串”,因为字符串的实际内部字节表示不是固定的,并且是您不应该依赖的 python 解释器的实现细节(参见PEP3993,在同一系统不同的字符串可以使用不同的内部编码)。

    这也意味着要获得字符串的字节表示,您确实需要对其进行编码,从而指定编码。

    顺便说一句,astring.encode("utf-8") 没有错(并且已经返回了一个bytes,你不需要在你的代码中额外的bytes(...)),因为在 utf-8 中单个字符可以表示为多个字节。

    【讨论】:

    • 但无论如何我都不工作。我在unicode 错误或ascii 错误中崩溃。在这种特殊情况下,.encode('utf8') 解决了这个问题,但在其他情况下,我需要输入.encode('ascii')。此外,如果我确实编码了一个 unicode 链,我会将编码加倍......
    • 不确定我明白你的意思。您不会将任何编码加倍:它从内部编码(隐藏且对您而言无关紧要)转换为 utf-8。你有没有.encode('utf-8') 不起作用的情况?为什么在某些情况下需要使用 .encode('ascii') ? ascii 字符串总是可以用 utf-8 编码
    【解决方案3】:

    您应该可以在字符串的引号前添加b

    >>> astring = b'\xb0'
    >>> astring
    b'\xb0'
    >>> bytes(astring)
    b'\xb0'
    >>>
    

    b 放在字符串之前使其成为bytes 对象。没有更多的UnicodeEncodeError

    【讨论】:

    • 这不是这个问题的答案,我的 `u'\xb0' 只是一个例子
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-07
    • 2019-08-29
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    相关资源
    最近更新 更多