比较:import 语句与 __import__ 函数 [英] Comparison: import statement vs __import__ function
问题描述
作为问题在正常情况下使用内置__import__()
的后续,我进行了几次测试,结果出人意料.
我在这里比较了一个经典的 import
语句和对 __import__
内置函数的调用的执行时间.为此,我在交互模式下使用以下脚本:
导入时间定义测试(模块):t1 = timeit.timeit("import {}".format(module))t2 = timeit.timeit("{0} = __import__('{0}')".format(module))打印(导入语句:",t1)打印(__import__函数:",t2)print("t(statement) {} t(function)".format("<" if t1 < t2 else ">"))
在链接的问题中,这里是导入 sys
以及其他一些标准模块时的比较:
到目前为止一切顺利,import
比 __import__()
快.这对我来说很有意义,因为正如我在链接帖子中所写的那样,我发现 IMPORT_NAME
指令与 CALL_FUNCTION
相比被优化是合乎逻辑的,当后者导致调用 __import__
.
但是当涉及到不那么标准的模块时,结果相反:
<预><代码>>>>测试('麻木')导入语句:0.18907936340054476__import__ 函数:0.15840019037769792t(语句)>t(函数)>>>测试('tkinter')导入语句:0.3798560809537861__import__ 函数:0.15899962771786136t(语句)>t(函数)>>>测试(pygame")导入语句:0.6624641952621317__import__ 函数:0.16268579177259568t(语句)>t(函数)执行时间差异背后的原因是什么?import
语句在标准模块上更快的实际原因是什么?另一方面,为什么 __import__
函数与其他模块一起更快?
使用 Python 3.6 进行测试
timeit
衡量的是总执行时间,但是模块的第一次导入,无论是通过 import
还是__import__
,比后续的要慢——因为它是唯一一个实际执行模块初始化的.它必须在文件系统中搜索模块的文件,加载模块的源代码(最慢)或之前创建的字节码(慢但比解析 .py
文件快一点)或共享库(对于 C 扩展),执行初始化代码,并将模块对象存储在 sys.modules
中.后续导入将跳过所有这些并从 sys.modules
中检索模块对象.
如果你颠倒顺序,结果就会不同:
导入时间定义测试(模块):t2 = timeit.timeit("{0} = __import__('{0}')".format(module))t1 = timeit.timeit("import {}".format(module))打印(导入语句:",t1)打印(__import__函数:",t2)print("t(statement) {} t(function)".format("<" if t1 < t2 else ">"))测试('麻木')导入语句:0.4611093703134608__import__ 函数:1.275512785926014t(语句)
获得无偏见结果的最佳方法是导入一次,然后进行计时:
导入时间定义测试(模块):exec("import {}".format(module))t2 = timeit.timeit("{0} = __import__('{0}')".format(module))t1 = timeit.timeit("import {}".format(module))打印(导入语句:",t1)打印(__import__函数:",t2)print("t(statement) {} t(function)".format("<" if t1 < t2 else ">"))测试('麻木')导入语句:0.4826306561727307__import__ 函数:0.9192819125911029t(语句)
所以,是的,import
总是比 __import__
快.
As a followup to the question Using builtin __import__()
in normal cases, I lead a few tests, and came across surprising results.
I am here comparing the execution time of a classical import
statement, and a call to the __import__
built-in function.
For this purpose, I use the following script in interactive mode:
import timeit
def test(module):
t1 = timeit.timeit("import {}".format(module))
t2 = timeit.timeit("{0} = __import__('{0}')".format(module))
print("import statement: ", t1)
print("__import__ function:", t2)
print("t(statement) {} t(function)".format("<" if t1 < t2 else ">"))
As in the linked question, here is the comparison when importing sys
, along with some other standard modules:
>>> test('sys')
import statement: 0.319865173171288
__import__ function: 0.38428380458522987
t(statement) < t(function)
>>> test('math')
import statement: 0.10262547545597034
__import__ function: 0.16307580163101054
t(statement) < t(function)
>>> test('os')
import statement: 0.10251490255312312
__import__ function: 0.16240755669640627
t(statement) < t(function)
>>> test('threading')
import statement: 0.11349136644972191
__import__ function: 0.1673617034957573
t(statement) < t(function)
So far so good, import
is faster than __import__()
.
This makes sense to me, because as I wrote in the linked post, I find it logical that the IMPORT_NAME
instruction is optimized in comparison with CALL_FUNCTION
, when the latter results in a call to __import__
.
But when it comes to less standard modules, the results reverse:
>>> test('numpy')
import statement: 0.18907936340054476
__import__ function: 0.15840019037769792
t(statement) > t(function)
>>> test('tkinter')
import statement: 0.3798560809537861
__import__ function: 0.15899962771786136
t(statement) > t(function)
>>> test("pygame")
import statement: 0.6624641952621317
__import__ function: 0.16268579177259568
t(statement) > t(function)
What is the reason behind this difference in the execution times?
What is the actual reason why the import
statement is faster on standard modules?
On the other hand, why is the __import__
function faster with other modules?
Tests lead with Python 3.6
timeit
measures the total execution time, but the first import of a module, whether through import
or __import__
, is slower than subsequent ones - because it's the only one that actually performs module initialization. It has to search the filesystem for the module's file(s), load the module's source code (slowest) or previously created bytecode (slow but a bit faster than parsing the .py
files) or shared library (for C extensions), execute the initialization code, and store the module object in sys.modules
. Subsequent imports get to skip all that and retrieve the module object from sys.modules
.
If you reverse the order the results will be different:
import timeit
def test(module):
t2 = timeit.timeit("{0} = __import__('{0}')".format(module))
t1 = timeit.timeit("import {}".format(module))
print("import statement: ", t1)
print("__import__ function:", t2)
print("t(statement) {} t(function)".format("<" if t1 < t2 else ">"))
test('numpy')
import statement: 0.4611093703134608
__import__ function: 1.275512785926014
t(statement) < t(function)
The best way to get non-biased results is to import it once and then do the timings:
import timeit
def test(module):
exec("import {}".format(module))
t2 = timeit.timeit("{0} = __import__('{0}')".format(module))
t1 = timeit.timeit("import {}".format(module))
print("import statement: ", t1)
print("__import__ function:", t2)
print("t(statement) {} t(function)".format("<" if t1 < t2 else ">"))
test('numpy')
import statement: 0.4826306561727307
__import__ function: 0.9192819125911029
t(statement) < t(function)
So, yes, import
is always faster than __import__
.
这篇关于比较:import 语句与 __import__ 函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!