【问题标题】:Best way to convert string to bytes in Python 3?在 Python 3 中将字符串转换为字节的最佳方法?
【发布时间】:2011-11-26 23:28:46
【问题描述】:

似乎有两种不同的方法可以将字符串转换为字节,如TypeError: 'str' does not support the buffer interface的答案所示

这些方法中哪一种会更好或更Pythonic?还是只是个人喜好问题?

b = bytes(mystring, 'utf-8')

b = mystring.encode('utf-8')

【问题讨论】:

  • 使用编码/解码更常见,也许更清晰。
  • @LennartRegebro 我解雇了。即使它更常见,阅读“bytes()”我知道它在做什么,而 encode() 不会让我觉得它正在编码为字节。
  • @erm3nda 这是使用它的一个很好的理由,直到它确实感觉像那样,那么你离Unicode zen又近了一步。
  • @LennartRegebro 我觉得使用bytes(item, "utf8") 已经足够好了,因为显式优于隐式,所以...str.encode( ) 默认默认为字节,让您更倾向于Unicode-zen 但更少显式-禅。 “共同”也不是我喜欢遵循的术语。此外,bytes(item, "utf8") 更像 str()b"string" 符号。如果我很菜鸟无法理解您的原因,我深表歉意。谢谢。
  • @erm3nda 如果您阅读了接受的答案,您会看到encode() 没有调用bytes(),相反。当然这不是很明显,这就是我问这个问题的原因。

标签: python string character-encoding python-3.x


【解决方案1】:

如果您查看bytes 的文档,它会将您指向bytearray

bytearray([source[, encoding[, errors]]])

返回一个新的字节数组。 bytearray 类型是 0

可选的源参数可用于以几种不同的方式初始化数组:

如果是字符串,还必须给出编码(以及可选的错误)参数; bytearray() 然后使用 str.encode() 将字符串转换为字节。

如果它是一个整数,则该数组将具有该大小,并将使用空字节进行初始化。

如果是符合buffer接口的对象,会使用该对象的只读缓冲区来初始化bytes数组。

如果是iterable,则必须是0

如果没有参数,则会创建一个大小为 0 的数组。

所以bytes 可以做的不仅仅是编码一个字符串。 Pythonic 允许您使用任何有意义的源参数类型调用构造函数。

对于字符串编码,我认为some_string.encode(encoding)比使用构造函数更Pythonic,因为它是最自我记录的——“取这个字符串并用这个编码编码”比bytes(some_string, encoding)更清楚——使用构造函数时没有显式动词。

我检查了 Python 源代码。如果你使用CPython将一个unicode字符串传递给bytes,它会调用PyUnicode_AsEncodedString,这是encode的实现;因此,如果您自己调用encode,您只是跳过了一个间接级别。

另外,请参阅 Serdalis 的评论——unicode_string.encode(encoding) 也更加 Pythonic,因为它的倒数是 byte_string.decode(encoding),并且对称性很好。

【讨论】:

  • +1 因为有一个好的论据和来自 python 文档的引用。当您想要恢复字符串时,unicode_string.encode(encoding) 也可以与 bytearray.decode(encoding) 很好地匹配。
  • bytearray 在需要可变对象时使用。简单的strbytes 转换不需要它。
  • @EugeneHomyakov 这与bytearray 无关,只是bytes 的文档没有提供详细信息,他们只是说“这是bytearray 的不可变版本”所以我有从那里引用。
  • 请注意,如果您尝试将二进制数据转换为字符串,您很可能需要使用 byte_string.decode('latin-1') 之类的东西,因为 utf-8 不涵盖整个范围 0x00到 0xFF (0-255),查看 python docs 了解更多信息。
  • tl;dr 会有所帮助
【解决方案2】:

这比想象的要容易:

my_str = "hello world"
my_str_as_bytes = str.encode(my_str)
type(my_str_as_bytes) # ensure it is byte representation
my_decoded_str = my_str_as_bytes.decode()
type(my_decoded_str) # ensure it is string representation

【讨论】:

  • 他知道该怎么做,他只是在问哪种方式更好。请重新阅读问题。
  • 仅供参考:str.decode(bytes) 对我不起作用(Python 3.3.3 说“类型对象 'str' 没有属性 'decode'”)我改用 bytes.decode()
  • @Mike:使用obj.method() 语法而不是cls.method(obj) 语法,即使用bytestring = unicode_text.encode(encoding)unicode_text = bytestring.decode(encoding)
  • ... 即您不必要地创建了一个未绑定的方法,然后调用它传递 self 作为第一个参数
  • @KolobCanyon 这个问题已经展示了正确的方法——调用encode作为字符串的绑定方法。这个答案建议您改为调用未绑定的方法并将字符串传递给它。这是答案中唯一的新信息,而且是错误的。
【解决方案3】:

绝对最好的方法不是第 2 种,而是第 3 种。从 Python 3.0 开始,encode 的第一个参数 默认为 'utf-8'。因此最好的方法是

b = mystring.encode()

这也会更快,因为默认参数不会导致 C 代码中的字符串 "utf-8",而是 NULL,这要快得多检查!

这里有一些时间安排:

In [1]: %timeit -r 10 'abc'.encode('utf-8')
The slowest run took 38.07 times longer than the fastest. 
This could mean that an intermediate result is being cached.
10000000 loops, best of 10: 183 ns per loop

In [2]: %timeit -r 10 'abc'.encode()
The slowest run took 27.34 times longer than the fastest. 
This could mean that an intermediate result is being cached.
10000000 loops, best of 10: 137 ns per loop

尽管有警告,但重复运行后时间非常稳定 - 偏差仅为约 2%。


使用不带参数的encode() 与 Python 2 不兼容,因为在 Python 2 中默认字符编码是 ASCII

>>> 'äöä'.encode()
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)

【讨论】:

  • 这里只有相当大的区别,因为 (a) 字符串是纯 ASCII,这意味着内部存储已经是 UTF-8 版本,因此查找编解码器几乎是唯一涉及的成本, (b) 字符串很小,所以即使你必须编码,也不会有太大的区别。尝试使用'\u00012345'*10000。在我的笔记本电脑上都需要 28.8us;额外的 50ns 可能会在舍入误差中丢失。当然,这是一个非常极端的例子——但'abc' 在相反的方向上也同样极端。
  • Python Zen 声明显式优于隐式,这意味着显式'utf-8' 参数是首选参数。但是您已经明确表明,放弃参数会更快。这使得这是一个很好的答案,即使它不是最好的。
  • @MarkRansom 那么你实际使用了多少次int(s, 10) ;-)
  • 尽管 Python 2 不再受支持,但我怀疑在很长一段时间内都会有人处理一些遗留代码;如果没有其他原因,只是将其升级到最新版本的 Python!很高兴您最后没有删除对 Python 2 用户的警告。
【解决方案4】:

回答一个稍微不同的问题:

你有一个原始的 unicode 序列被保存到一个 str 变量中:

s_str: str = "\x00\x01\x00\xc0\x01\x00\x00\x00\x04"

您需要能够获取该 unicode 的字节文字(用于 struct.unpack() 等)

s_bytes: bytes = b'\x00\x01\x00\xc0\x01\x00\x00\x00\x04'

解决方案:

s_new: bytes = bytes(s, encoding="raw_unicode_escape")

参考(向上滚动查看标准编码):

Python Specific Encodings

【讨论】:

  • 这实际上正是我想要的。我不知道如何更好地表达我的问题。 :) 谢谢@Brent!
  • 这是我需要的答案,来自谷歌搜索“python 3 convert str to bytes binary”,这是最好的结果,看起来很有希望。还有更多有趣的问题——比如如何将 unicode 字符串转换为常规字符串(python 2.7):p
猜你喜欢
  • 2014-06-21
  • 2010-10-10
  • 1970-01-01
相关资源
最近更新 更多