如何从包中的兄弟模块导入?

Posted

技术标签:

【中文标题】如何从包中的兄弟模块导入?【英文标题】:How to import from sibling module in a package? 【发布时间】:2017-09-25 03:32:24 【问题描述】:

我的包有以下结构:

myPackage
 -- __init__.py <-- empty
 -- signal.py
 -- plot.py

signal.py 包含:

from plot import plot_signal

def build_filter():
   ...

def other_function():
   plot_signal()

plot.py 包含:

from signal import build_filter

def plot_signal():
   ...

def other_function():
   build_filter()

然后我的脚本使用了这个包,其中包含以下内容:

import myPackage as mp

mp.plot.plot_signal()

当我运行它时,我得到一个属性错误:module 'myPackage' has no attribute 'plot'

我不确定为什么它在我的包中将 plot 作为一个模块引用为属性,或者为什么将 myPackage 作为一个模块引用。

然后我尝试导入我的包并以不同的方式调用该函数:

from myPackage import plot, signal

plot.plot_signal()

但是,现在我收到一个导入错误:cannot import name 'build_filter',并且回溯指的是 plot.py,它试图从同级模块导入 build_filter() 函数。

我认为这与这两个模块使用彼此的函数并递归导入另一个模块这一事实有关。

组织这个包以便兄弟模块可以相互导入函数的正确方法是什么?

【问题讨论】:

@matino:我将语言标签更改为“python-3.x”,因为这显然是 OP 正在使用的(python 2 产生不同的错误消息)。你为什么把它放回“python”? @martineau - 我认为这个问题与所有版本的python有关,不管错误信息如何,但如果你愿意,可以随时恢复python-3x。 @matino:你在这两个版本中都试过你的解决方案了吗? @martineau - 是的,我做到了 【参考方案1】:

要使mp.plot.plot_signal() 工作,您必须在myPackage.__init__.py 中使用import plot。 另一件事是,在 plot.py 和 signal.py 中,您应该导入整个模块以避免循环导入:

信号.py:

import myPackage.plot

myPackage.plot.plot_signal()

plot.py

import myPackage.signal

myPackage.signal.build_filter()

您也可以在所有 3 个文件中使用相对导入,但它仅适用于 Python 3.x:

信号.py:

from . import plot

plot.plot_signal()

plot.py

from . import signal

signal.build_filter()

【讨论】:

完美,这似乎有效。有没有办法在这 3 个文件中使用相对导入,所以我不需要手动指定包名称? (这可能会在某个时候改变)

以上是关于如何从包中的兄弟模块导入?的主要内容,如果未能解决你的问题,请参考以下文章

为啥“导入模块”然后“从包导入模块”再次加载模块?

如何从包内的两个不同文件夹中导入一个模块,该模块导入另一个模块

如何检查 Python 包中的任何模块是不是从另一个包导入?

如何导入安装在站点包中的模块

如何让 React Native 仅在 Android 操作系统上从包中获取/导入功能

戈朗。从包中只导入一个文件