【问题标题】:Time taken by an import in Python在 Python 中导入所花费的时间
【发布时间】:2009-04-20 11:29:46
【问题描述】:

我想知道内置模块和用户定义模块的导入需要多长时间。

【问题讨论】:

  • 情况不同。请提供一些具体的场景或情况。
  • -1:在答案 cmets 中加入了额外的事实。新的事实应该放在问题中,而不是答案中。

标签: python import


【解决方案1】:

从 Python3.7 版本开始,新的-X importtime 选项可用。 要测量导入时间,只需使用该选项执行您的脚本,例如python -X importtime my_script.py.

供参考:

【讨论】:

【解决方案2】:

你可以测试一下这个运行

$ time python -c "import math"

但是,这对您有什么帮助?进口只发生一次,几乎永远不会成为瓶颈。一遍又一遍地导入同一个模块不会比导入一次慢很多,因为 Python 会跟踪哪些模块已经被导入。

你真正想要达到什么目的?

【讨论】:

  • 我有一个导入其他模块的主脚本。我需要计算需要多少时间
  • 当你使用多处理时,导入会发生多次
【解决方案3】:

要了解导入需要多长时间,最简单的方法可能是使用timeit module..

>>> import timeit
>>> t = timeit.Timer('import urllib')
>>> t.timeit(number = 1000000)
0.98621106147766113

所以导入 urllib 100 万次,只用了不到一秒钟(在 Macbook Pro 上)..

我有一个导入其他模块的主脚本。我需要计算需要多少时间

如果您指的是总脚本执行时间,在 Linux/OS X/Cygwin 上,您可以使用 time 命令运行脚本,例如:

$ time python myscript.py 

real    0m0.046s
user    0m0.024s
sys     0m0.020s

(请记住,这包括所有 Python 解释器的启动时间,以及实际的代码执行时间,尽管它是微不足道的)

另一种可能更有用的方法是分析脚本:

而不是运行您的代码

$ python myscript.py 

..你用..

$ python -m cProfile myscript.py
         1059 function calls in 0.015 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        1    0.002    0.002    0.015    0.015 myscript.py:1(<module>)
   [...]

我发现命令行输出不是很容易阅读,所以我几乎总是使用gprof2dot,它将分析信息变成漂亮的graphviz图:

$ python -m cProfile -o myscript.prof myscript.py
$ python gprof2dot.py -o myscript.dot -f pstats myscript.prof
$ dot -Tpng -o profile.png prof_runtest.dot -Gbgcolor=black

Example output (1429x1896px PNG)

【讨论】:

  • 嗯,我认为这实际上不会多次导入。它实际上只是在测试 Python 的模块缓存的性能。 reload(module) 也不具有与从头开始导入相同的行为。要真正回答作者的问题实际上是相当困难的,除非导入的时间足够大以至于一次测量一个调用是合理的。
【解决方案4】:

分析导入的一种方法是使用 bzr source code 中使用的 profile_imports 模块:

# put those two lines at the top of your script
import profile_imports
profile_imports.install()

# display the results
profile_imports.log_stack_info(sys.stderr)

除了为您提供导入时间之外,这还估计了编译正则表达式的时间,这通常是导致导入速度放缓的重要原因。

【讨论】:

    【解决方案5】:

    使用 cProfile:

    python -m cProfile yourscript.py
    

    【讨论】:

    • 我正在使用 IDLE。我遇到了 SyntaxError
    • 我给出的命令将是您从命令行运行的命令,而不是从 python 解释器中运行的命令。
    【解决方案6】:

    我在分析一个启动时间为几秒的大型遗留应用程序时遇到了这个问题。将内置导入器替换为进行一些分析的东西相对简单。下面是显示每个模块执行大约需要多长时间的一种 hacky 方式:

    import os
    import sys
    import time
    
    
    class ImportEventNode(object):
        def __init__(self, name, start_time, children=None, end_time=None):
            self.name = name
            self.start_time = start_time
            self.children = [] if children is None else children
            self.end_time = end_time
    
        def __repr__(self):
            return 'ImportEventNode({self.name}, {self.start_time}, children={self.children}, end_time={self.end_time})'.format(self=self)
    
        @property
        def total_time(self):
            return self.end_time - self.start_time
    
        @property
        def net_time(self):
            return self.total_time - sum(child.total_time for child in self.children)
    
    
    root_node = cur_node = None
    
    all_nodes = []
    old_import = __import__
    def __import__(*args, **kwargs):
        global root_node, cur_node
        name = args[0]
        if name not in sys.modules:
            t0 = time.time()
            if root_node is None:
                root_node = prev_node = cur_node = lcur_node = ImportEventNode(args[0], t0)
            else:
                prev_node = cur_node
                cur_node = lcur_node = ImportEventNode(name, t0)
                prev_node.children.append(cur_node)
            try:
                ret = old_import(*args, **kwargs)
            finally:
                lcur_node.end_time = time.time()
            all_nodes.append(lcur_node)
            cur_node = prev_node
            return ret
        else:
            return old_import(*args, **kwargs)
    
    
    __builtins__.__import__ = __import__
    

    运行一个简单的例子,下面是它在导入 scipy.stats 时的样子:

    :import scipy.stats
    :
    :nodes = sorted(all_nodes, key=(lambda x: x.net_time), reverse=True)
    :for node in nodes[:10]:
    :    print(node.name, node.net_time)
    :
    :<EOF>
    ('pkg_resources', 0.08431100845336914)
    ('', 0.05861020088195801)
    ('decomp_schur', 0.016885995864868164)
    ('PIL', 0.0143890380859375)
    ('scipy.stats', 0.010602712631225586)
    ('pkg_resources._vendor.packaging.specifiers', 0.007072925567626953)
    ('add_newdocs', 0.00637507438659668)
    ('mtrand', 0.005497932434082031)
    ('scipy.sparse.linalg', 0.005171060562133789)
    ('scipy.linalg', 0.004471778869628906)
    

    【讨论】:

      【解决方案7】:

      在 Windows 上使用 Python 2.4 进行测试 - 您可以自己尝试。

      >>> import time
      
      >>> ## Built-in module
      >>> def testTime():
              now = time.clock() # use time.time() on unix-based systems
              import math
              print time.clock() - now
      
      >>> testTime()
      7.54285810167e-006
      
      
      
      >>> ## My own module
      >>> def testTime():
              now = time.clock()
              import myBuiltInModule # Not its actual name ;-)
              print time.clock() - now
      
      >>> testTime()
      0.00253174635324
      >>> testTime()
      3.70158777141e-006
      

      因此,缓存模块与从头引入的模块之间存在很大差异。为了说明,我们可以重新加载模块:

      >>> def testTime():
              now = time.clock()
              reload(myBuiltInModule )
              print time.clock() - now
      
      
      >>> testTime()
      0.00250017809526
      

      【讨论】:

        【解决方案8】:

        这是对szymonskjern 建议的扩展,将Python Profilerstuna 结合起来。

        首先安装金枪鱼

        pip install tuna
        

        然后,创建一个 python 扩展文件并将其命名为您想要的任何名称。这里我们将其命名为timit_package.py

        在此文件中,包括内置模块和用户定义模块。

        这里,我只测试

        import mne
        

        然后,在终端中

        python -mcProfile -o program.prof timit_package.py
        

        等待几秒钟,然后将以下行粘贴到终端中

        tuna program.prof
        

        将生成一个浏览器以及配置文件。

        我正在使用 python 3.9 进行测试

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-03-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-30
          相关资源
          最近更新 更多