Python 中的相对导入
Posted
技术标签:
【中文标题】Python 中的相对导入【英文标题】:Relative imports in Python 【发布时间】:2011-05-09 16:47:11 【问题描述】:大家好——我正在使用 来拉扯我的头发。我已经在 SO 和其他论坛上阅读了 30 次文档和大量帖子 - 似乎仍然不起作用。
我的目录结构目前是这样的
src/
__init__.py
main.py
components/
__init__.py
expander.py
language_id.py
utilities/
__init__.py
functions.py
我希望 expander.py 和 language_id.py 能够访问功能模块。我运行 python main.py,它可以通过 from components.expander import * 和 components.language_id import * 很好地访问模块。
但是,expander 和 language_id 里面的代码来访问功能模块:
from ..utilities.functions import *
我收到此错误:
ValueError: Attempted relative import beyond toplevel package
我已经检查了很多次,它似乎遵循文档。有人知道这里出了什么问题吗?
【问题讨论】:
您已经找到了解决方案,但要解释为什么需要它:包应该是完全独立的。当您在其中运行 main.py 时,它不会将 src/ 视为一个包。 【参考方案1】:没关系,我解决了:
src/
main.py
mod/
__init__.py
components/
__init__.py
expander.py
language_id.py
utilities/
__init__.py
functions.py
main.py 然后将子包称为:
from mod.components.expander import *
from mod.utilities.functions import *
expander.py 和 language_id.py 可以通过以下方式访问 functions.py:
from ..utilities.functions import *
但有趣的是,我在 expander.py 使用的 components 目录中有一个文本文件。但是,在运行时它无法找到该文件,即使它位于同一目录中。我将文本文件移动到与 main.py 相同的目录并且它工作。似乎违反直觉。
【讨论】:
所有新模块导入的东西都坏了,不直观。 从您启动程序的工作目录中打开文本文件,而导入是相对于脚本的位置。您可以在模块中使用 __file__ 来查找其路径,从而引用同一目录中的内容,尽管它不是很优雅。如果文本文件是程序的静态数据,则将其制成 Python 模块并导入可能会更容易。 您可以使用pkgutil.get_data()
(docs.python.org/library/pkgutil#pkgutil.get_data) 来检索文件,使用模块命名空间来定位它们。例如,raw_data = pkgutil.get_data('mod.components', 'data.txt')
将从文件中检索原始二进制数据。
对于那些仍然认为这个答案有效的人,这对我有用:sys.path.append(path)
解决方案是删除项目根目录中的 __init__ 文件。不需要创建一个新文件夹“mod”,以上是关于Python 中的相对导入的主要内容,如果未能解决你的问题,请参考以下文章