Using Builtin __import__() In Normal Cases
Solution 1:
Here is a small "benchmark". Let's define two functions:
def f1():
import sys
def f2():
sys = __import__('sys')
Bytecode comparison:
>>> 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
The generated bytecodes have the same number of instructions, but they are different. So what about the timing?
>>> timeit.timeit(f1)
0.4096750088112782
>>> timeit.timeit(f2)
0.474958091968411
It turns out that the __import__
way is slower.
In addition, it is far less readable than the classical import
statement.
Conclusion: stick with import
.
Now for a bit of interpretation...
I suppose that calling __import__
is slower than executing an import
statement, because the bytecode generated by the latter is optimised.
Take a look at the instructions: the bytecode for __import__
just look like any other function call, with a CALL_FUNCTION
instruction.
On the other hand, the import
statement results in a IMPORT_NAME
instruction, which definetely looks like something dedicated to imports, and is probably executed in an optimised way by the interpreter.
As a matter of fact, the third instruction is the only true difference between the two bytecodes.
So the difference between the two functions lies in the difference between IMPORT_NAME
and CALL_FUNCTION
.
Post a Comment for "Using Builtin __import__() In Normal Cases"