在默认情况下所有文本文字均为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'])))

10-07 19:03
查看更多