在默认情况下所有文本文字均为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'对象”。
好的,因此我们将其显式设置为
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,就像我应该的那样;但这显然超出了Python 2和Python 3之间对
__import__
的期望。如何在保持
__import__
设置的情况下,在fromlist
调用中完成其unicode_literals
参数,使其在Python 2和Python 3下都能正常工作? 最佳答案
回想str
对于python2和python3的工作方式有所不同(请参阅@BrenBarn的评论),因此:
main_module = __import__(main_module_name, fromlist=[str('bar')])
或更一般地
main_module = __import__(main_module_name, fromlist=list(map(str, ['bar'])))