【发布时间】:2014-12-15 05:27:00
【问题描述】:
在默认情况下所有文本文字都是 Unicode 的世界中,我应该怎么做才能使 __import__ 在 Python 2 和 3 中都工作?
我正在慢慢学习如何编写可在 Python 2(2.6 或更高版本)和 Python 3(3.2 或更高版本)下运行的 Python 代码。
我相信,这需要确保文本文字默认为 Unicode:
from __future__ import unicode_literals
并在需要时使用b'wibble' 明确指定字节文字。
不过,__import__ 内置函数正在出错。
一个人为的、琐碎的项目布局:
$ mkdir fooproject/
$ cd fooproject/
$ mkdir foo/
$ printf "" > foo/__init__.py
$ mkdir foo/bar/
$ printf "" > foo/bar/__init__.py
这是该项目的简单fooproject/setup.py:
from __future__ import unicode_literals
main_module_name = 'foo'
main_module = __import__(main_module_name, fromlist=['bar'])
assert main_module.bar
在 Python 2 下失败,但在 Python 3 下运行良好:
$ python2 ./setup.py
Traceback (most recent call last):
File "./setup.py", line 4, in <module>
main_module = __import__(main_module_name, fromlist=['bar'])
TypeError: Item in ``from list'' not a string
$ python3 ./setup.py
默认情况下,我们故意将未加修饰的字符串设为 Unicode。通过“不是一个 字符串”,我认为 Python 2 的意思是“不是‘字节’对象”。
好的,所以我们将其显式设置为 bytes 文字:
from __future__ import unicode_literals
main_module_name = 'foo'
main_module = __import__(main_module_name, fromlist=[b'bar'])
assert main_module.bar
现在 Python 2 很满意,但是 Python 3 抱怨:
$ python2 ./setup.py
$ python3 ./setup.py
Traceback (most recent call last):
File "./setup.py", line 4, in <module>
main_module = __import__(main_module_name, fromlist=[b'bar'])
File "<frozen importlib._bootstrap>", line 2281, in
_handle_fromlist
TypeError: hasattr(): attribute name must be string
所以我故意将未修饰的字符串默认设置为 Unicode,就像我应该做的那样;但这显然打破了__import__ 在 Python 2 和 Python 3 之间的期望。
我怎样才能获得 __import__ 调用,完成其 fromlist 参数,在 Python 2 和 Python 3 下正常工作,保持 unicode_literals 设置?
【问题讨论】:
-
您可以编写一个将字符串传递给的函数,它会检查版本并返回 unicode 或 bytestring 版本。
-
@BrenBarn,这正是
str()的行为方式!
标签: python migration portability python-unicode