unicode_literals and type()

13

我在支持Python2和Python3的type()调用方面遇到了问题。以下是示例代码:

from __future__ import unicode_literals

name='FooClass'
type(name, (dict,), {})

在 Python3 上没有问题,但是在 Python2 上存在问题:

Traceback (most recent call last):
  File "test.py", line 6, in <module>
    type(name, (dict,), {})
TypeError: type() argument 1 must be string, not unicode

这与在Python 2.6中使用unicode_literals有什么要注意的地方?有关。 在那个问题中,有人建议将其类型转换为字节串,因此我天真地想到使用six.b()

一个“假”的字节串文字。数据应始终为普通字符串文字。 在Python 2中,b()返回8位字符串。 在Python 3中,使用拉丁-1编码将数据编码为字节。

所以看起来像这样:

from __future__ import unicode_literals
import six

name='FooClass'
type(six.b(name), (dict,), {})

但在Python2和Python3上都失败了:

$ python2 test.py 
Traceback (most recent call last):
  File "test.py", line 6, in <module>
    type(six.b(name), (dict,), {})
TypeError: type() argument 1 must be string, not unicode

$ python3 test.py 
Traceback (most recent call last):
  File "test.py", line 6, in <module>
    type(six.b(name), (dict,), {})
TypeError: type() argument 1 must be str, not bytes

看起来 实际上type() 在 python2 中需要一个 python3 的字节字符串(bytestring),而在 python3 中需要一个 python2 的 Unicode 字符串(unicode string)。

您觉得呢?

我是否有什么不理解的地方?

还是说在 python 2 和 3 上真的存在不兼容性问题?

难道没有 任何 方法可以让相同的 type() 调用同时支持 2 和 3 吗?

在这种情况下,像 six 这样的工具应该为 type() 提供一个包装器吗?


谢谢,可以了,虽然我确信我已经测试过了... - jpic
1个回答

16

six.b 的实现假设您不会使用 unicode_literals(并且按照文档所述传递字符串字面值),因此 Python 2 的实现只是 def b(s): return s,因为 Python 2 字符串字面值已经是字节字符串。

要么在此模块中不使用 unicode_literals,要么使用(如注释所示)str(name)。在 Python 3 中,这是无操作的。在 Python 2 中,它会将 Unicode 字符串静默转换为字节字符串(假定某些编码,我无法记住,但它是 ASCII 的超集,所以您应该没问题)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接