【问题标题】:How can I track python imports [closed]如何跟踪 python 导入 [关闭]
【发布时间】:2009-11-28 00:15:35
【问题描述】:

我在向一个非常大的应用程序添加一些新代码时遇到周期性导入问题,我正在尝试确定哪些文件最有可能导致此问题。有什么方法可以跟踪哪些文件导入哪些文件?我做了一些查找并找到了 python trace 命令,但它只是在主要的 python 库中显示了一堆活动。

我基本上是在寻找一个可以向我展示如下内容的应用:

App1 >>imports>> App2,App3.method
App2 >>imports>> App3,etc

我可以浏览我所有的文件,但我不想,这是一个大应用程序。

【问题讨论】:

    标签: python import


    【解决方案1】:

    这里有一个简单(而且有点初级;-)的方法来跟踪模块名称方面的“谁在尝试导入什么”:

    import inspect
    import __builtin__
    savimp = __builtin__.__import__
    
    def newimp(name, *x):
      caller = inspect.currentframe().f_back
      print name, caller.f_globals.get('__name__')
      return savimp(name, *x)
    
    __builtin__.__import__ = newimp
    

    例如(已将其保存为tracimp.py):

    $ python -c 'import tracimp; import email; import sys; import email.mime'
    email __main__
    sys email
    email.mime email
    sys __main__
    email.mime __main__
    

    如您所见,“包装”内置 __import__ 的一个特定特征是,它不会因为正在导入的模块已经在 sys.modules 中而被静音:因为照顾它是__import__ 的工作之一,我们的包装器被调用为两个模块“第一次加载”和那些刚刚从 sys.modules 获取的模块,因为它们之前已经被导入.当您尝试诊断循环导入时,这应该非常方便(它归结为在有向图中查找循环,其边缘由两个模块名称标识 - 导入和导入器 - 这种简单的方法在每个模块上打印输出线)。

    【讨论】:

      【解决方案2】:

      您可以使用以下脚本之一来制作 python 模块依赖图:

      【讨论】:

      • Snakefood 最终成为我想要的。不过,它需要一些按摩才能使其适用于大量文件。
      • @Jeff:是的,设置确实需要一些工作,阅读文档是必须的。我很高兴你能够让它工作!
      • 3个链接全部失效,2020年该回复也可删除。
      【解决方案3】:

      尝试使用python -v 运行您的程序。它将跟踪导入的顺序。

      另一个选项是pylint,它会提醒您各种问题,包括循环导入。

      【讨论】:

      • 我想在 uwsgi 下运行 python 时使用这个 -v 选项。我最终将它添加到我的 uwsgi ini 文件中:env=PYTHONVERBOSE=1 输出进入普通 uwsgi 日志文件中指定的内容。
      【解决方案4】:

      在 python 中应该不可能进行循环导入,因为它会在再次导入之前检查模块是否已经导入。一个模块只能导入一次,不管调用多少次。

      来自http://groups.google.com/group/comp.lang.python/browse_thread/thread/1d80a1c6db2b867c?pli=1:

      导入非常简单 真的。请记住以下几点:

      'import' 和 'from xxx import yyy' 是 可执行语句。他们执行 当正在运行的程序达到 行。

      如果模块不在 sys.modules 中, 然后导入创建新模块 进入 sys.modules 然后执行 模块中的代码。它不是 将控制权返回给调用模块 直到执行完成。

      如果模块确实存在于 sys.modules 然后导入只是返回 模块是否已完成 执行。这就是为什么 循环导入可能会返回模块 其中似乎部分为空。

      最后,执行脚本运行在 一个名为 __main__ 的模块,导入 以自己的名字命名的脚本将创建 一个不相关的新模块 __main__.

      把很多东西放在一起,你 不应该得到任何惊喜 导入模块。

      【讨论】:

      • 很可能得到循环导入。它们不会无限循环,但会产生问题,因为两个文件相互导入,因此在需要时未定义函数。
      • python 中的循环导入只有在您专门从一个模块导入一个项目,而另一个模块导入您时才会出现问题。如果您这样做: 在 A.py 中:导入 B 在 B.py 中:导入 A 那么即使它们周期性地相互导入,您也不会遇到问题,因为引用被推迟到导入项目的实际执行/使用。只有当您从另一个尚未定义的模块请求项目(即在导入时请求引用)时才会导致问题。
      猜你喜欢
      • 2018-05-04
      • 1970-01-01
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多