Python 2为什么在使用“ import…as ...”时尝试将模块作为包属性获取?

问题描述 投票:2回答:1

请考虑以下目录结构:

.
└── package
    ├── __init__.py
    ├── a.py
    └── b.py

__init__.py文件为空。两个模块package.apackage.b分别包含:

# package.a
import sys

print('package.b' in sys.modules)
import package.b as b

spam = 'ham'
print("{} says b is {}".format(__name__, b))
# package.b
import package.a

print("{} says package.a.spam is {}".format(__name__, repr(package.a.spam)))

使用Python 3.x(特别是3.8),当我从根目录运行python -c "from __future__ import print_function; import package.b"时,得到

True
package.a says b is <module 'package.b' from 'C:\\[...]\\package\\b.py'>
package.b says package.a.spam is 'ham'

但使用Python 2.x(具体是2.7)我得到

True
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "package\b.py", line 1, in <module>
    import package.a
  File "package\a.py", line 4, in <module>
    import package.b as b
AttributeError: 'module' object has no attribute 'b'

问题是:什么需要这种区别?此更改记录在哪里,例如Python文档,PEP或类似文档?


[导入到package.bpackage.a尚未完成初始化,因此package.b的模块对象尚未添加为package的模块对象的属性。但是模块对象本身存在(将其添加到sys.modules中),因此将名称b绑定到该对象应该没有任何麻烦,这就是Python 3的信念? Python 2似乎并未将其直接绑定到模块对象,而是试图通过从'b'的模块对象获取名为package的属性来获取它。

据我所知,文档中没有这样的规范。

Import statement (Python 3.8)

如果成功检索到所请求的模块,它将以以下三种方式之一在本地名称空间中提供:

  • 如果模块名称后跟as,则名称后跟as直接绑定到导入的模块。
  • [...]

Import statement (Python 2.7)

导入语句的第一种形式将本地名称空间中的模块名称绑定到模块对象,然后继续导入下一个标识符(如果有)。如果模块名称后跟as,则名称后跟as作为模块的本地名称。


注意:

  • from package import b中使用package/a.py会产生相同的结果,只是误差有所不同(即ImportError而不是AttributeError)。我怀疑ImportError只是包装了基础AttributeError
  • import package.b中使用package/a.py不会在导入Py2时给出AttributeError。但是,当然,稍后在打印调用中引用package.b会在Py2和Py3中都产生AttributeError

请考虑以下目录结构:。 package──包├──__init__.py├──a.py└──b.py __init__.py文件为空。两个模块package.a和package.b分别包含:...

python python-import python-2.x importerror circular-dependency
1个回答
0
投票

如果您这样做

© www.soinside.com 2019 - 2024. All rights reserved.