Python 相对进口测试我的理智
Python relative imports testing my sanity
编辑:循环依赖问题是 from .. import auth
不起作用的原因,请参阅下面我自己的回答。为大家干杯。
我正在尝试 Python 中的相关导入,同时重新组织一些代码,本来应该花 10 分钟的事情现在花费了无数时间。这是我的文件结构:
project/
/__init__.py
/application.py
/lib/
/__init__.py
/auth.py
/utils.py
/views/
/__init__.py
/login_view.py
/test.py
在login_view.py
我有:
from . import auth
产生:ImportError: cannot import name auth
然而这有效:
from ..auth import untoken, req_auth_or_error
我不明白:auth
只比 login_view
高一级,为什么是 ..
而不是 .
?
这也失败并出现同样的错误:
from .. import auth
在 test.py
中,我尝试了以下操作:
import types
from .. import *
def imports():
for name, val in globals().items():
if isinstance(val, types.ModuleType):
print 'imported: ', val.__name__
imports()
这导致:
imported: lib.utils
imported: lib.views
imported: types
...我不知道为什么 lib.auth
没有导入。我做错了什么?
我是运行这样的代码(绝对路径是/scratch/project/
):
$ cd project/
$ ./application.py
在第一种情况下,from . import auth
.
表示包 views
。这就是为什么 Python 找不到它的原因。
但是,要避免这些问题,recommended 使用绝对导入而不是相对导入。
如果导入时再上一级目录怎么办?
from ... import auth
问题是循环依赖,而不是相对导入。
确实,需要 ..
从父目录加载模块。
然而在 auth.py
的某处我有一个 import views.login_view
。我相信 login_view.py
中的 from .. import auth
试图在 auth
模块自行加载时导入它。这可能是 from ..auth import untoken
工作的原因,因为这些功能已经加载。
在 Python 中,导入中的一个点表示当前 包 ,而不是当前模块。
然后每增加一个点代表一个新的水平"parentness"(好吧这个词不存在但我认为它很好地表达了我的意思)。
所以你在第一个案例中注意到的行为是正常的。
对于你的第二种情况,我用这些内容复制了你的层次结构:
application.py
lib.views import login_view
print("oh yeah")
login_view.py
lib.views import login_view
print("oh my god")
项目目录中的 ... 和 运行 application.py 不会导致任何错误。我得到以下输出:
$ python application.py
oh my god
oh yeah
但是,在 application.py
中添加 from lib.views import test
(使用与您提供的完全相同的 test.py
内容)会得到以下输出,显示某些 lib
模块是未加载:
$ python application.py
oh my god
imported: types
imported: lib.views
imported: lib.auth
oh yeah
缺少 lib.utils
模块 :/
我的想法是,由于 from .. import *
没有命名:没有包、没有模块、没有函数或变量或任何东西,import 语句只是简单地导入任何东西。显示的 modules/packages 只是之前加载的那个。
也就是说,有一种方法可以通过使用 __all__
魔法变量来强制执行 "correct" 行为,它定义了在使用 splat 导入时加载哪些模块,在 lib/__init__.py
文件:
__all__ = ['auth', 'views', 'utils']
执行此操作后,运行 application.py
文件再次显示以下内容:
$ python application.py
oh my god
imported: types
imported: lib.auth
imported: lib.views
imported: lib.utils
oh yeah
编辑:循环依赖问题是 from .. import auth
不起作用的原因,请参阅下面我自己的回答。为大家干杯。
我正在尝试 Python 中的相关导入,同时重新组织一些代码,本来应该花 10 分钟的事情现在花费了无数时间。这是我的文件结构:
project/
/__init__.py
/application.py
/lib/
/__init__.py
/auth.py
/utils.py
/views/
/__init__.py
/login_view.py
/test.py
在login_view.py
我有:
from . import auth
产生:ImportError: cannot import name auth
然而这有效:
from ..auth import untoken, req_auth_or_error
我不明白:auth
只比 login_view
高一级,为什么是 ..
而不是 .
?
这也失败并出现同样的错误:
from .. import auth
在 test.py
中,我尝试了以下操作:
import types
from .. import *
def imports():
for name, val in globals().items():
if isinstance(val, types.ModuleType):
print 'imported: ', val.__name__
imports()
这导致:
imported: lib.utils
imported: lib.views
imported: types
...我不知道为什么 lib.auth
没有导入。我做错了什么?
我是运行这样的代码(绝对路径是/scratch/project/
):
$ cd project/
$ ./application.py
在第一种情况下,from . import auth
.
表示包 views
。这就是为什么 Python 找不到它的原因。
但是,要避免这些问题,recommended 使用绝对导入而不是相对导入。
如果导入时再上一级目录怎么办?
from ... import auth
问题是循环依赖,而不是相对导入。
确实,需要 ..
从父目录加载模块。
然而在 auth.py
的某处我有一个 import views.login_view
。我相信 login_view.py
中的 from .. import auth
试图在 auth
模块自行加载时导入它。这可能是 from ..auth import untoken
工作的原因,因为这些功能已经加载。
在 Python 中,导入中的一个点表示当前 包 ,而不是当前模块。
然后每增加一个点代表一个新的水平"parentness"(好吧这个词不存在但我认为它很好地表达了我的意思)。 所以你在第一个案例中注意到的行为是正常的。
对于你的第二种情况,我用这些内容复制了你的层次结构:
application.py
lib.views import login_view
print("oh yeah")
login_view.py
lib.views import login_view
print("oh my god")
项目目录中的 ... 和 运行 application.py 不会导致任何错误。我得到以下输出:
$ python application.py
oh my god
oh yeah
但是,在 application.py
中添加 from lib.views import test
(使用与您提供的完全相同的 test.py
内容)会得到以下输出,显示某些 lib
模块是未加载:
$ python application.py
oh my god
imported: types
imported: lib.views
imported: lib.auth
oh yeah
缺少 lib.utils
模块 :/
我的想法是,由于 from .. import *
没有命名:没有包、没有模块、没有函数或变量或任何东西,import 语句只是简单地导入任何东西。显示的 modules/packages 只是之前加载的那个。
也就是说,有一种方法可以通过使用 __all__
魔法变量来强制执行 "correct" 行为,它定义了在使用 splat 导入时加载哪些模块,在 lib/__init__.py
文件:
__all__ = ['auth', 'views', 'utils']
执行此操作后,运行 application.py
文件再次显示以下内容:
$ python application.py
oh my god
imported: types
imported: lib.auth
imported: lib.views
imported: lib.utils
oh yeah