在正常情况下使用内置__import __()

时间:2017-09-12 09:58:34

标签: python python-import

这是我检查__import__()

的效果的地方
In [9]: %%timeit
   ...: math = __import__('math')
   ...: sqrt = math.sqrt
   ...: sqrt(7894561230)
   ...: 
The slowest run took 11.16 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 534 ns per loop

In [10]: %%timeit
    ...: from math import sqrt
    ...: sqrt(7894561230)
    ...: 
    ...: 
The slowest run took 10.23 times longer than the fastest. This could mean that an intermediate result is being cached.
1000000 loops, best of 3: 979 ns per loop

内置__import__模块似乎比传统的导入方式更快,

因此我可以在代码中使用它,或者在执行此操作时是否有任何重大损害,__import__ doc并未声明这样做有任何损害。

但它说明了

  

除了您想要的情况外,直接使用__import__()的情况很少见   导入一个名称仅在运行时已知的模块。

所以我的问题是它是否可以在正常情况下使用。或者它有什么缺点吗?

1 个答案:

答案 0 :(得分:3)

这是一个小“基准”。我们定义两个函数:

def f1():
    import sys

def f2():
    sys = __import__('sys')

字节码比较:

>>> dis.dis(f1)
  5           0 LOAD_CONST               1 (0)
              2 LOAD_CONST               0 (None)
              4 IMPORT_NAME              0 (sys)
              6 STORE_FAST               0 (sys)
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE

>>> dis.dis(f2)
  8           0 LOAD_GLOBAL              0 (__import__)
              2 LOAD_CONST               1 ('sys')
              4 CALL_FUNCTION            1
              6 STORE_FAST               0 (sys)
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE

生成的字节码具有相同数量的指令,但它们是不同的。 那么时机呢?

>>> timeit.timeit(f1)
0.4096750088112782

>>> timeit.timeit(f2)
0.474958091968411

事实证明__import__方式较慢。 此外,它的可读性远低于经典的import语句。

结论:坚持import

现在进行一些解释......

我认为调用__import__比执行import语句慢,因为后者生成的字节码已经过优化。

看一下说明:__import__的字节码看起来就像任何其他函数调用一样,带有CALL_FUNCTION指令。 另一方面,import语句导致IMPORT_NAME指令,它定义为专用于导入的内容,并且可能由解释器以优化的方式执行。

事实上,第三条指令是两个字节码之间唯一真正的区别。 因此,这两个函数之间的区别在于IMPORT_NAMECALL_FUNCTION之间的区别。