【问题标题】:Profile Python import times分析 Python 导入时间
【发布时间】:2016-04-17 18:43:41
【问题描述】:

有没有办法找出 Python 中哪些导入耗时最长?查看python -m cProfile <script> 的输出,它似乎不包括import 语句(可以理解给定潜在的巨大依赖树)。最初我认为它确实如此,因为我看到一行 __import__() 调用,但我认为这实际上可能是因为某处的代码明确调用它,只有 import 语句的玩具程序没有一行。

现在我只是在使用:

start = time.time()
import <module>
print '%s / time: %f' % (<module>, time.time()-start)

围绕每个模块,但它不会递归地分析它以查看导入中的哪个导入可能会增加时间。

【问题讨论】:

  • 为什么需要分析导入?它们只发生一次,要么你需要它们,要么你不需要它们。
  • 如果您正在寻找导入系统中的瓶颈,那您就找错地方了。
  • 要添加到其他 cmets,如果您看到需要时间的导入,那是因为您在这些文件中的代码不在类/函数定义内且不受 @987654327 保护@ 除非有严格的需求,否则您可以将此代码放在 init() 之类的内容中并对其进行概要分析。不保护此代码也会导致每次导入该文件时都会运行代码。
  • @danielu13 这就是我的问题的意图,找出哪些导入进行了大量初始化(一个需要 22 秒)。虽然对总运行时间来说一点也不重要,但我很好奇那个时间是从哪里来的。
  • 这是一个庞大的代码库,具有很大的依赖树,因此仅找到要重构的初始化代码会很困难。您不必担心重复导入,Python 只初始化一次导入 (stackoverflow.com/a/296062/873472)。

标签: python profiling python-import


【解决方案1】:

正如 danielu13 的评论中所述,您真正想要分析的是在导入该模块时在该模块内执行的代码。

似乎 cProfile 在其输出中包含了在导入时执行的此代码。对于模块级代码,它显示为&lt;module&gt;。 许多包被导入为__init__.py 文件,因此gprof2dot 显示__init__:23:&lt;module&gt;(行号可能不同),它并不能告诉您文件来自哪个包。

使用 cprofilev,您可以找出哪些文件(以及包)花费的时间最多。

一个旁注:在某些情况下,分析导入实际上是有意义的。在我的系统上,导入模块 networkx (https://networkx.github.io/) 需要 1.7 秒。

【讨论】:

    【解决方案2】:

    这是一个完全合理的问题。例如,尝试加速 CLI 应用程序的冷启动是有意义的。 Python 3.7 现在提供了打印导入时间的选项:https://docs.python.org/3/using/cmdline.html#envvar-PYTHONPROFILEIMPORTTIME

    你可以运行:

    python -X importtime myscript.py
    

    或:

    PYTHONPROFILEIMPORTTIME=1 myscript.py
    

    编辑:要查看这些结果,我推荐tuna

    【讨论】:

    • 这些数字的单位是什么?文档中没有提到。
    【解决方案3】:

    一个非常简单且非分层的 Python 2.7 解决方案,打印模块名称和自上一个模块以来的导入时间:

    LAST_TIME = time.time()
    
    class ImportHook(object):
        def find_module(self, fullname, path=None):
            global LAST_TIME
            cur_time = time.time()
            delta = cur_time - LAST_TIME
            long_time = '!!!!!!!!!!!!!!\n' * 10 if delta > 0.05 else ''
            print '%0.3f %s \n %s' % (delta, long_time, fullname),
            LAST_TIME = cur_time
    
    import sys
    sys.meta_path.insert(0, ImportHook())
    

    【讨论】:

    • 我很想知道为什么那个计时器有效。这是实际的导入时间,还是只是自上次在 meta_path 中搜索模块以来经过的时间?
    • @RyandeKleer ,只是上次搜索的增量。
    猜你喜欢
    • 1970-01-01
    • 2018-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-23
    • 1970-01-01
    • 2017-02-22
    • 2014-05-11
    相关资源
    最近更新 更多