Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python import X or from X import Y? (performance)

If there is a library from which I'm going to use at least two methods, is there any difference in performance or memory usage between the following?

from X import method1, method2

and

import X
like image 989
Tom Avatar asked Aug 28 '10 18:08

Tom


People also ask

Is from import faster than import?

There is a difference, because in the import x version there are two name lookups: one for the module name, and the second for the function name; on the other hand, using from x import y , you have only one lookup. As you can see, using the form from x import y is a bit faster.

Does the order of imports matter in Python?

Import order does not matter. If a module relies on other modules, it needs to import them itself. Python treats each . py file as a self-contained unit as far as what's visible in that file.

Should I use relative or absolute imports Python?

With your new skills, you can confidently import packages and modules from the Python standard library, third party packages, and your own local packages. Remember that you should generally opt for absolute imports over relative ones, unless the path is complex and would make the statement too long.

What does from X import Y mean in Python?

from x import y will only import y from module x . This way, you won't have to use dot-notation. (Bonus: from x import * will refer to the module in the current namespace while also replacing any names that are the same) import x as y will import module x which can be called by referring to it as y.


3 Answers

There is a difference, because in the import x version there are two name lookups: one for the module name, and the second for the function name; on the other hand, using from x import y, you have only one lookup.

You can see this quite well, using the dis module:

import random
def f_1():
    random.seed()

dis.dis(f_1)
     0 LOAD_GLOBAL              0 (random)
     3 LOAD_ATTR                0 (seed)
     6 CALL_FUNCTION            0
     9 POP_TOP
    10 LOAD_CONST               0 (None)
    13 RETURN_VALUE

from random import seed

def f_2():
    seed()

dis.dis(f_2)
     0 LOAD_GLOBAL              0 (seed)
     3 CALL_FUNCTION            0
     6 POP_TOP
     7 LOAD_CONST               0 (None)
    10 RETURN_VALUE

As you can see, using the form from x import y is a bit faster.

On the other hand, import x is less expensive than from x import y, because there's a name lookup less; let's look at the disassembled code:

def f_3():
    import random

dis.dis(f_3)
     0 LOAD_CONST               1 (-1)
     3 LOAD_CONST               0 (None)
     6 IMPORT_NAME              0 (random)
     9 STORE_FAST               0 (random)
    12 LOAD_CONST               0 (None)
    15 RETURN_VALUE

def f_4():
    from random import seed

dis.dis(f_4)
     0 LOAD_CONST               1 (-1)
     3 LOAD_CONST               2 (('seed',))
     6 IMPORT_NAME              0 (random)
     9 IMPORT_FROM              1 (seed)
    12 STORE_FAST               0 (seed)
    15 POP_TOP
    16 LOAD_CONST               0 (None)
    19 RETURN_VALUE

I do not know the reason, but it seems the form from x import y looks like a function call, and therefore is even more expensive than anticipated; for this reason, if the imported function is used only once, it means it would be faster to use import x, while if it is being used more than once, it becomes then faster to use from x import y.

That said, as usual, I would suggest you not following this knowledge for your decision on how to import modules and functions, because this is just some premature optimization.
Personally, I think in a lot of cases, explicit namespaces are much more readable, and I would suggest you doing the same: use your own sense of esthetic :-)

like image 115
rob Avatar answered Oct 17 '22 10:10

rob


There is no memory or speed difference (the whole module has to be evaluated either way, because the last line could be Y = something_else). Unless your computer is from the 1980s it doesn't matter anyways.

like image 23
Jochen Ritzel Avatar answered Oct 17 '22 10:10

Jochen Ritzel


It can matter if you are calling a function a lot of times in a loop (millions or more). Doing the double dictionary lookup will eventually accumulate. The example below shows a 20% increase.

Times quoted are for Python 3.4 on a Win7 64 bit machine. (Change the range command to xrange for Python 2.7).

This example is highly based on the book High Performance Python, although their third example of local function lookups being better no longer seemed to hold for me.

import math
from math import sin

def tight_loop_slow(iterations):
    """
    >>> %timeit tight_loop_slow(10000000)
    1 loops, best of 3: 3.2 s per loop
    """
    result = 0
    for i in range(iterations):
        # this call to sin requires two dictionary lookups
        result += math.sin(i)

def tight_loop_fast(iterations):
    """
    >>> %timeit tight_loop_fast(10000000)
    1 loops, best of 3: 2.56 s per loop
    """
    result = 0
    for i in range(iterations):
        # this call to sin only requires only one lookup
        result += sin(i)
like image 9
DStauffman Avatar answered Oct 17 '22 10:10

DStauffman