【发布时间】:2009-04-20 11:29:46
【问题描述】:
我想知道内置模块和用户定义模块的导入需要多长时间。
【问题讨论】:
-
情况不同。请提供一些具体的场景或情况。
-
-1:在答案 cmets 中加入了额外的事实。新的事实应该放在问题中,而不是答案中。
我想知道内置模块和用户定义模块的导入需要多长时间。
【问题讨论】:
从 Python3.7 版本开始,新的-X importtime 选项可用。
要测量导入时间,只需使用该选项执行您的脚本,例如python -X importtime my_script.py.
供参考:
【讨论】:
tuna。取自这里:github.com/nschloe/tuna
你可以测试一下这个运行
$ time python -c "import math"
但是,这对您有什么帮助?进口只发生一次,几乎永远不会成为瓶颈。一遍又一遍地导入同一个模块不会比导入一次慢很多,因为 Python 会跟踪哪些模块已经被导入。
你真正想要达到什么目的?
【讨论】:
要了解导入需要多长时间,最简单的方法可能是使用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
【讨论】:
reload(module) 也不具有与从头开始导入相同的行为。要真正回答作者的问题实际上是相当困难的,除非导入的时间足够大以至于一次测量一个调用是合理的。
分析导入的一种方法是使用 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)
除了为您提供导入时间之外,这还估计了编译正则表达式的时间,这通常是导致导入速度放缓的重要原因。
【讨论】:
使用 cProfile:
python -m cProfile yourscript.py
【讨论】:
我在分析一个启动时间为几秒的大型遗留应用程序时遇到了这个问题。将内置导入器替换为进行一些分析的东西相对简单。下面是显示每个模块执行大约需要多长时间的一种 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)
【讨论】:
在 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
【讨论】:
这是对szymon 和skjern 建议的扩展,将Python Profilers 和tuna 结合起来。
首先安装金枪鱼
pip install tuna
然后,创建一个 python 扩展文件并将其命名为您想要的任何名称。这里我们将其命名为timit_package.py。
在此文件中,包括内置模块和用户定义模块。
这里,我只测试
import mne
然后,在终端中
python -mcProfile -o program.prof timit_package.py
等待几秒钟,然后将以下行粘贴到终端中
tuna program.prof
将生成一个浏览器以及配置文件。
我正在使用 python 3.9 进行测试
【讨论】: