Python 3 中的相对导入
relative import in Python 3
假设我的项目结构如下:
myproject
├── calendar.py
├── foo.py
└── __init__.py
在foo.py,我有
from calendar import isleap
我认为在 Python 3.x 中没有使用明确的 .calendar 上面的代码应该加载内置日历模块而不是我自己的日历模块,但显然我的本地 calendar.py 仍在导入并且它抛出错误,因为 mypkg/calendar.py 中没有 'isleap'。为什么我的本地日历模块被导入到这里?
我必须将 calendar.py 重命名为 cal.py 才能完成这项工作..
看来你的路径或目录结构设置有误。
鉴于以下结构,您的日历模块的全名应该是 myproject.calendar
。您可以通过打印模块的 __name__
属性来检查这一点。为此,您的程序用于导入本地模块的路径必须是包含 myproject
.
的文件夹
myproject
├── calendar.py
├── foo.py
└── __init__.py
看来您使用的路径实际上是myproject
。意思是 calendar.py
变成了根级模块 calendar
,而不是 myproject.calendar
。 Python 比内置模块更喜欢本地模块,因此导入您的 calendar
模块。
更常见的情况是您可能会这样做。
MyProjectFolder
├── main.py
└── myproject
├── calendar.py
├── foo.py
└── __init__.py
然后 运行 你的程序是这样的:
#! /bin/bash
cd /path/to/MyProjectFolder
python main.py
Python 将检查您的本地模块并首先由 import
加载它们。
from calendar import isleap
将首先在您的语言环境包中搜索模块 calendar
。如果找不到,它将从内置库中导入 calendar
.
from .calendar import isleap
只会从您的语言环境模块 calendar
导入。如果未找到,则引发异常 ImportError
.
这就是为什么你应该在包中使用相对导入。
您可以使用类似的技巧来导入内置库而不检查本地模块。但这只是一个技巧。我永远不会在生产中使用它。你最好重命名你的模块 calendar
.
import imp, sys
f, pathname, desc = imp.find_module("calendar", sys.path[1:])
calendar = imp.load_module("calendar", f, pathname, desc)
f.close()
from calendar import isleap
from __future__ import absolute_import
是 Python 3 上的默认值。因此 from calendar import isleap
语句导入顶级模块 calendar
.
如果您看到其他结果;这意味着要么你没有使用 Python 3,要么你正试图 运行 包内的一个 python 模块作为脚本(myproject
目录本身在 sys.path
).如果是后者,那么您的 calendar.py
成为顶级模块并且(由于当前目录位于 sys.path
中的 stdlib 目录之前)from calendar import isleap
从当前目录导入 calendar.py
。 "Never add a package directory, or any directory inside a package, directly to the Python path"
为避免这种情况,请不要直接从 python 包中 运行 模块,例如,不要这样做:cd myproject; python foo.py
。改为这样做:python -mmyproject.foo
(或者你可以 define what scripts should be run in setup.py
or create a similar script manually: from myproject import foo; foo.main()
)。
如果你想 运行 一个 Python 包作为脚本然后创建 myproject/__main__.py
然后 运行 python -mmyproject
.
如果你想在Python3中进行相对导入;明确地做到这一点,例如,在 myproject/foo.py
中:
from .calendar import something
或者进行绝对导入:
from myproject.calendar import something
假设我的项目结构如下:
myproject
├── calendar.py
├── foo.py
└── __init__.py
在foo.py,我有
from calendar import isleap
我认为在 Python 3.x 中没有使用明确的 .calendar 上面的代码应该加载内置日历模块而不是我自己的日历模块,但显然我的本地 calendar.py 仍在导入并且它抛出错误,因为 mypkg/calendar.py 中没有 'isleap'。为什么我的本地日历模块被导入到这里?
我必须将 calendar.py 重命名为 cal.py 才能完成这项工作..
看来你的路径或目录结构设置有误。
鉴于以下结构,您的日历模块的全名应该是 myproject.calendar
。您可以通过打印模块的 __name__
属性来检查这一点。为此,您的程序用于导入本地模块的路径必须是包含 myproject
.
myproject
├── calendar.py
├── foo.py
└── __init__.py
看来您使用的路径实际上是myproject
。意思是 calendar.py
变成了根级模块 calendar
,而不是 myproject.calendar
。 Python 比内置模块更喜欢本地模块,因此导入您的 calendar
模块。
更常见的情况是您可能会这样做。
MyProjectFolder
├── main.py
└── myproject
├── calendar.py
├── foo.py
└── __init__.py
然后 运行 你的程序是这样的:
#! /bin/bash
cd /path/to/MyProjectFolder
python main.py
Python 将检查您的本地模块并首先由 import
加载它们。
from calendar import isleap
将首先在您的语言环境包中搜索模块 calendar
。如果找不到,它将从内置库中导入 calendar
.
from .calendar import isleap
只会从您的语言环境模块 calendar
导入。如果未找到,则引发异常 ImportError
.
这就是为什么你应该在包中使用相对导入。
您可以使用类似的技巧来导入内置库而不检查本地模块。但这只是一个技巧。我永远不会在生产中使用它。你最好重命名你的模块 calendar
.
import imp, sys
f, pathname, desc = imp.find_module("calendar", sys.path[1:])
calendar = imp.load_module("calendar", f, pathname, desc)
f.close()
from calendar import isleap
from __future__ import absolute_import
是 Python 3 上的默认值。因此 from calendar import isleap
语句导入顶级模块 calendar
.
如果您看到其他结果;这意味着要么你没有使用 Python 3,要么你正试图 运行 包内的一个 python 模块作为脚本(myproject
目录本身在 sys.path
).如果是后者,那么您的 calendar.py
成为顶级模块并且(由于当前目录位于 sys.path
中的 stdlib 目录之前)from calendar import isleap
从当前目录导入 calendar.py
。 "Never add a package directory, or any directory inside a package, directly to the Python path"
为避免这种情况,请不要直接从 python 包中 运行 模块,例如,不要这样做:cd myproject; python foo.py
。改为这样做:python -mmyproject.foo
(或者你可以 define what scripts should be run in setup.py
or create a similar script manually: from myproject import foo; foo.main()
)。
如果你想 运行 一个 Python 包作为脚本然后创建 myproject/__main__.py
然后 运行 python -mmyproject
.
如果你想在Python3中进行相对导入;明确地做到这一点,例如,在 myproject/foo.py
中:
from .calendar import something
或者进行绝对导入:
from myproject.calendar import something