可移植代码:python2和python3之间的参数字符串类型

2024-06-25 22:54:36 发布

您现在位置:Python中文网/ 问答频道 /正文

在一个所有文本文本都默认为Unicode的世界中,我应该怎么做才能使__import__同时在python2和python3中工作?在

我正在慢慢地学习如何编写可以在python2(2.6或更高版本)和python3(3.2或更高版本)下运行的Python代码。在

我认为,这就需要注意确保文本文字在默认情况下是Unicode的:

from __future__ import unicode_literals

如果需要,则使用b'wibble'显式指定字节文本。在

但是__import__内置函数正在中断。在

精心设计的、琐碎的项目布局:

^{pr2}$

以下是该项目的一个简单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。不是一个 “字符串”,我想Python2的意思是“不是一个‘字节’对象”。在

好的,我们将显式地将其设置为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,正如我所期望的那样;但这显然打破了python2和python3之间__import__的期望。在

我怎样才能得到__import__调用,并完成它的fromlist参数,在python2和python3下都能正常工作,同时保持unicode_literals设置?在


Tags: namefrompy文本importmainsetupunicode
2条回答

到目前为止,我能想到的最好的是一个包装器函数,它可以根据Python版本转换类型:

from __future__ import unicode_literals

import sys

fromlist_expects_type = str
if sys.version_info < (3, 0):
    fromlist_expects_type = bytes

def import_module(
        name, globals=None, locals=None, fromlist=(), level=0):
    """ Import specified module, together with options used by __import__.

        :param module_name: Text string of the module name to import.
        :param fromlist: List of names of attributes in the module to
            also import.
        :return: The module object.

        The built-in ``__import__`` function accepts a ``fromlist``
        parameter, but expects different string types between Python 2
        and Python 3. Python 2 only allows text string items; Python 3
        only allows byte string items.

        This function's ``fromlist`` parameter must have items of text
        string (Unicode) type only; the items are converted depending
        on the running Python version.

        """
    module_fromlist = ()
    if fromlist:
        module_fromlist = [
                fromlist_expects_type(attr_name) for attr_name in fromlist]
    module = __import__(
            name=name,
            globals=globals,
            locals=locals,
            fromlist=module_fromlist,
            level=level)

    return module

main_module_name = 'foo'
main_module = import_module(main_module_name, fromlist=['bar'])

这太难用了,我可能犯了几个错误。当然这是Python中的一个bug,我需要这样做吗?在

回想一下str对python2和python3的作用是不同的(参见@BrenBarn的评论),因此:

main_module = __import__(main_module_name, fromlist=[str('bar')])

或者更广泛地说

^{pr2}$

相关问题 更多 >