循环导入的python变通方法

循环导入的python变通方法,python,python-2.7,import,module,circular-dependency,Python,Python 2.7,Import,Module,Circular Dependency,好的,就是这样 我不想泄露我的代码,但如果你真的需要,我会的。我有两个模块,需要从对方那里得到一些信息。这些模块称为webhandler和datahandler 在webhandler中,我有一行: import datahandler 在datahandler中,我还有一行: import webhandler 现在我知道这是一个糟糕的代码,像这样的循环导入会导致代码运行两次(这是我试图避免的) 但是,datahandler模块需要从webhandler模块访问多个函数,webhandl

好的,就是这样

我不想泄露我的代码,但如果你真的需要,我会的。我有两个模块,需要从对方那里得到一些信息。这些模块称为webhandler和datahandler

在webhandler中,我有一行:

import datahandler 
在datahandler中,我还有一行:

import webhandler
现在我知道这是一个糟糕的代码,像这样的循环导入会导致代码运行两次(这是我试图避免的)

但是,datahandler模块需要从webhandler模块访问多个函数,webhandler模块需要访问datahandler模块中生成的多个变量。除了将函数移动到不同的模块之外,我看不到任何解决方法,但这会破坏我程序的组织,并且模块命名没有任何逻辑意义

有什么帮助吗

webhandler模块需要访问datahandler模块中生成的几个变量

将任何“生成的”数据推送到第三个位置可能是有意义的。因此
datahandler
函数在适当的时候调用
config.setvar(name,value)
,而
webhandler
函数在需要的时候调用
config.getvar(name)
config
将是第三个子模块,包含您编写的简单的
setvar
getvar
函数(围绕设置/获取全局字典元素的包装将是最简单的方法)

然后
datahandler
代码将
importwebhandler,config
,但是
webhandler
只需要
importconfig


然而,我同意,需要这样一个问题暴露了这样一个事实,即您可能还没有像您所想的那样清晰、合乎逻辑地完成设计。如果是我,我会重新思考模块的划分方式。

循环依赖是一种代码气味。如果您有两个相互依赖的模块,那么这是一个非常糟糕的迹象,您应该重新构造代码

有几种不同的方法可以做到这一点;哪一个是最好的取决于您正在做什么,以及每个模块的哪些部分实际上被另一个模块使用

  • 一个非常简单的解决方案是合并两个模块,这样您只有一个模块,它只依赖于自身,或者更确切地说,依赖于自己的内容。这很简单,但是因为您以前已经分离了模块,所以很可能您以这种方式引入了新问题,因为您不再分离关注点
  • 另一个解决方案是确保实际需要依赖项。如果一个模块中只有少数几个部分依赖于另一个模块,那么您可以以不再需要循环依赖的方式移动这些位,或者使循环依赖不再成为问题
  • 更好的解决方案可能是将依赖项移动到一个单独的新模块中。如果命名真的是最难的问题,那么你可能做得对。这可能会“破坏[你的]程序的组织”,但由于你有循环依赖,你的设置本身就有问题

其他人所说的不进行循环导入是最好的解决方案,但如果您最终完全需要它们,通常只需要其中一个模块的一种方法或功能。因此,您可以安全地执行以下操作:

#modA.py
import modB

#modB.py
def methodDependingOnA():
    import modA
    ...

每次调用函数时执行导入都会有一点开销,但除非一直调用,否则开销相当低。

SqlAlchemy使用依赖项注入模式,其中所需的模块由装饰器传递给函数:

@util.dependencies(“sqlalchemy.orm.util”)
定义标识键(cls、orm_util、*args、**kwargs):
返回orm_util.identity_键(*args,**kwargs)

这种方法基本上与在函数内部执行
导入
相同,但性能稍好一些。

不要导入整个模块,只需从中导入所需的内容即可<来自datahandler import myfunc的代码>和来自webhandler import domthing的
仍然不喜欢它,它要么抛出错误,要么仍然运行代码两次
来自X import Y的
对您毫无帮助。
X
中的所有代码仍将运行。在我的系统上,导入一次后,添加的导入时间约为380纳秒,因此如果在微秒或毫秒运行函数上下文中使用,您不会注意到导入时间。