检测循环进口 [英] Detecting circular imports

查看:51
本文介绍了检测循环进口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理一个包含约30个独特模块的项目。它的设计不太好,因此在向项目添加一些新功能时通常会创建循环导入。

I'm working with a project that contains about 30 unique modules. It wasn't designed too well, so it's common that I create circular imports when adding some new functionality to the project.

当然,当我添加循环导入时,我不知道。有时很明显,当我收到类似 AttributeError之类的错误时,我已经进行了循环导入:'module'对象没有属性'attribute'我明确定义了属性 。但是有时候,代码不会因为使用方式而引发异常。

Of course, when I add the circular import, I'm unaware of it. Sometimes it's pretty obvious I've made a circular import when I get an error like AttributeError: 'module' object has no attribute 'attribute' where I clearly defined 'attribute'. But other times, the code doesn't throw exceptions because of the way it's used.

所以,我的问题是:


是否可以通过编程方式检测何时以及在何处进行循环进口?

Is it possible to programmatically detect when and where a circular import is occuring?

到目前为止,我唯一能想到的解决方案是拥有一个模块 importTracking ,其中包含一个字典 importingModules ,一个函数 importInProgress(file),它会增加 importingModules [file] 的值,如果大于1,则抛出错误,而函数 importComplete(file)会减小 importingModules [file] 。所有其他模块如下所示:

The only solution I can think of so far is to have a module importTracking that contains a dict importingModules, a function importInProgress(file), which increments importingModules[file], and throws an error if it's greater than 1, and a function importComplete(file) which decrements importingModules[file]. All other modules would look like:

import importTracking
importTracking.importInProgress(__file__)
#module code goes here.
importTracking.importComplete(__file__)

但这看上去真的很讨厌,必须有一个

But that looks really nasty, there's got to be a better way to do it, right?

推荐答案

为避免更改每个模块,您可以将导入跟踪功能保留在导入挂钩,或在自定义的 __ import __ 您可以坚持使用内置插件-后者一次可能会更好,因为即使导入的模块被调用,也会调用 __ import __ sys.modules 中已经存在,在循环导入时就是这种情况。

To avoid having to alter every module, you could stick your import-tracking functionality in a import hook, or in a customized __import__ you could stick in the built-ins -- the latter, for once, might work better, because __import__ gets called even if the module getting imported is already in sys.modules, which is the case during circular imports.

对于该实现,我只使用一组正在导入过程中的模块,类似于(benjaoming编辑:插入从原始文件派生的片段):

For the implementation I'd simply use a set of the modules "in the process of being imported", something like (benjaoming edit: Inserting a working snippet derived from original):

beingimported = set()
originalimport = __import__
def newimport(modulename, *args, **kwargs):
    if modulename in beingimported:
        print "Importing in circles", modulename, args, kwargs
        print "    Import stack trace -> ", beingimported
        # sys.exit(1) # Normally exiting is a bad idea.
    beingimported.add(modulename)
    result = originalimport(modulename, *args, **kwargs)
    if modulename in beingimported:
        beingimported.remove(modulename)
    return result
import __builtin__
__builtin__.__import__ = newimport

这篇关于检测循环进口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆