循环导入的python解决方法
Posted
技术标签:
【中文标题】循环导入的python解决方法【英文标题】:python workaround for circular import 【发布时间】:2015-10-02 05:29:46 【问题描述】:好的,就是这样。
我宁愿不泄露我的代码,但如果你真的需要它,我会的。我有两个模块需要彼此一点。这些模块称为 webhandler 和 datahandler。
在 webhandler 我有一行:
import datahandler
在数据处理程序中我还有另一行:
import webhandler
现在我知道这是很糟糕的代码,像这样的循环导入会导致代码运行两次(这是我试图避免的)。
然而,datahandler 模块需要从 webhandler 模块访问几个函数,而 webhandler 模块需要访问在 datahandler 模块中生成的几个变量。除了将函数移动到不同的模块之外,我没有看到任何解决方法,但这会破坏我的程序的组织并且对模块命名没有逻辑意义。
有什么帮助吗?
【问题讨论】:
不要导入整个模块,只导入你需要的。from datahandler import myfunc
和 from webhandler import domthing
还是不喜欢,要么抛出错误,要么仍然运行代码两次
from X import Y
对你一点帮助都没有。 X
中的所有代码仍将运行。
【参考方案1】:
webhandler 模块需要访问在 datahandler 模块中生成的几个变量
将任何“生成”的数据推送到第三个位置可能是有意义的。所以datahandler
函数在适当的时候调用config.setvar( name, value )
,webhandler
函数在需要的时候调用config.getvar( name )
。 config
将是第三个子模块,包含您编写的简单 setvar
和 getvar
函数(围绕设置/获取全局字典元素的包装器将是最简单的方法)。
那么datahandler
代码将是import webhandler, config
但webhandler
只需要import config
。
我同意poke 的观点,但是,对这样一个问题的需要暴露了您可能还没有像您想象的那样整齐和合乎逻辑地完成设计的事实。如果是我,我会重新思考模块的划分方式。
【讨论】:
【参考方案2】:循环依赖是代码异味的一种形式。如果您有两个相互依赖的模块,那么这是一个非常糟糕的信号,您应该重组您的代码。
有几种不同的方法可以做到这一点;哪个最好取决于您在做什么,以及每个模块的哪些部分实际被另一个模块使用。
一个非常简单的解决方案是合并两个模块,这样您就只有一个模块,它只依赖于自身,或者更确切地说,依赖于它自己的内容。这很简单,但是由于您之前已经分离了模块,因此您可能会以这种方式引入新问题,因为您不再需要分离关注点。 另一种解决方案是确保确实需要依赖项。如果一个模块只有几个部分依赖于另一个模块,也许您可以以不再需要循环依赖的方式移动这些位,或者utilize the way imports work 使循环依赖不再是问题。 更好的解决方案可能是将依赖项移动到单独的新模块中。如果命名真的是最难的问题,那么你可能做对了。它可能“破坏 [你的] 程序的组织”,但由于你有循环依赖,所以无论如何你的设置存在一些固有的错误。【讨论】:
【参考方案3】:其他人所说的不进行循环导入是最好的解决方案,但如果您最终绝对需要它们,它通常只在其中一个模块的一种方法或函数中。因此,您可以安全地这样做:
#modA.py
import modB
#modB.py
def methodDependingOnA():
import modA
...
每次调用函数时进行导入都会产生少量开销,但除非一直被调用,否则开销会相当低。
【讨论】:
在我的系统上,导入一次后的导入时间约为 380 纳秒,因此如果在微秒或毫秒运行的函数上下文中使用,您不会注意到导入时间。 【参考方案4】:SqlAlchemy 使用依赖注入模式,其中所需的模块由装饰器传递给函数:
@util.dependencies("sqlalchemy.orm.util")
def identity_key(cls, orm_util, *args, **kwargs):
return orm_util.identity_key(*args, **kwargs)
这种方法与在函数内部执行import
基本相同,但性能稍好。
【讨论】:
以上是关于循环导入的python解决方法的主要内容,如果未能解决你的问题,请参考以下文章
Golang中 import cycle not allowed 的解决方法
Python包的相对导入时出现“ ‘Parent module ' not loaded, cannot perform relative import”的解决方法
Python:导入KMeans库失败;Kmeans报错及解决方法;NameError: name ‘KMeans‘ is not defined