python - 从 Python 中的相对路径导入 : strange behavior

标签 python namespaces python-import

据我了解 python docs , from package import x声明应该只绑定(bind) x , 但不是 package , 进入当前命名空间。 但实际上,如果package是一个相对的名字,它有时也是绑定(bind)的!

让我举个例子。考虑以下文件层次结构:

root/
  package/
    __init__.py
    subpackage/
      __init__.py

分包/__init__.py:

foo = 42

包/__init__.py:

from os import name
from .subpackage import foo

print(globals().get('name'))
print(globals().get('os'))
print(globals().get('foo'))
print(globals().get('subpackage'))

现在让我们从 root 运行 python(v2 或 v3)解释器目录并执行

>>> import package

前三行输出是可预测的:

posix
None
42

但是最后一个是<module 'package.subpackage' ...>而不是 None ,这让我有些困惑。

我错过了什么吗?这是预期的行为吗?这是什么原因?


在这种情况下,情况对我来说似乎更加奇怪:

root/
  __init__.py  # Empty.
  package/
    __init__.py
  another_package/
    __init__.py

另一个包/__init__.py:

bar = 33

包/__init__.py:

from ..another_package import bar

print(globals().get('another_package'))

现在我在根运行这个:

>>> import root.package
None  # OK.
>>> dir(root.package)
['__builtins__', ..., '__path__', 'bar']  # OK.
>>> dir(root)
['__builtins__', ..., '__path__', 'another_package', 'package']  # What?!

为什么 another_package出现在 dir(root)

最佳答案

重要的是要意识到模块最多加载一次(除非它们是明确的 reloaded )。如果一个模块在多个模块中被导入,同一个模块object 被它们全部引用。例如:

模块 M.py

bar = 10

模块 A.py

import M
M.bar = 4

模块 B.py

import M
M.bar = 6

所以:

>>> import M
>>> M.bar
10
>>> import A
>>> M.bar  # A is referencing the same M module object!!
4
>>> import B
>>> M.bar # B is referencing the same M module object!!
6

现在,当语句 from ..another_package import bar 被执行时,它基本上等同于执行 from root.another_package import bar。由于 another_package 确实是 root 包中的一个模块,语句成功并产生以下效果(可能还有更多,但为了这个目的,让我们关注这 3 个) :

  1. root 已加载如果之前未加载(它的 __init__.py 已运行)
  2. bar 导入到当前命名空间
  3. another_package 作为属性添加到 root 模块对象

一些开发人员并不完全了解第 1 项和第 3 项。

回到你的问题:让我们看看执行 import root.package 时会发生什么,顺序如下:

  1. root__init__.py 已运行(因为 root 尚未加载)
  2. package__init__.py 已运行(因为 package 尚未加载)
  3. from ..another_package import bar 的执行具有上述副作用,最值得注意的是,(是的。对象。每个模块只有一个,还记得吗?)模块对象root 添加了 another_package 属性。

这解释了为什么 another_package 出现在 rootdir 中。

关于python - 从 Python 中的相对路径导入 : strange behavior,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28786108/

相关文章:

python - 如何让程序不抛出 "Error: Can' t load Floyd's algorithm library”

python - 从 pandas 中的列列表创建新列

Python(和 Django)最佳导入实践

python - 带正则化的 Numpy 线性回归

Python变量名称.错误

c++ - 命名空间改变函数定义

web-services - 通过 Web 服务传递序列化对象与传递对象

asp.net-mvc-2 - ASP.NET MVC - 嵌套应用程序中的 Controller 名称

python - Virtualenv 中的导入错误

python - 在python项目中使用相对路径读取文件