user765443
user765443

Reputation: 1892

import module or any component in python

during code implementation, I got suggestion we should import only specific feature which will reduce time but I got some different result. Am I doing some thing wrong.

python -m timeit "from subprocess import call" (suggested method which is taking more time)
1000000 loops, best of 3: 1.01 usec per loop

python -m timeit "import subprocess"
1000000 loops, best of 3: 0.525 usec per loop

Upvotes: 0

Views: 100

Answers (4)

Blckknght
Blckknght

Reputation: 104692

The performance difference between import subprocess and from subprocess import call is likely to be very small (probably it will be completely dominated by the overhead involved in actually creating and running other processes). However, there are some small performance differences between them, and it might be worth seeing where they come from.

Here's the code I used to get a feel for what they do. I use the dis module to disassemble compiled Python bytecode, so we can see what is happening:

import dis

from_import_src = """
from subprocess import call
foo = call
"""

plain_import_src = """
import subprocess
foo = subprocess.call
"""

from_bytecode = compile(from_import_src, "from_import", "exec")
plain_bytecode = compile(plain_import_src, "plain_import", "exec")

print("from ... import ...")
dis.dis(from_bytecode)

print("\nimport ...")
dis.dis(plain_bytecode)

The output:

from ... import ...
  2           0 LOAD_CONST               0 (0) 
              3 LOAD_CONST               1 (('call',)) 
              6 IMPORT_NAME              0 (subprocess) 
              9 IMPORT_FROM              1 (call) 
             12 STORE_NAME               1 (call) 
             15 POP_TOP              

  3          16 LOAD_NAME                1 (call) 
             19 STORE_NAME               2 (foo) 
             22 LOAD_CONST               2 (None) 
             25 RETURN_VALUE         

import ...
  2           0 LOAD_CONST               0 (0) 
              3 LOAD_CONST               1 (None) 
              6 IMPORT_NAME              0 (subprocess) 
              9 STORE_NAME               0 (subprocess) 

  3          12 LOAD_NAME                0 (subprocess) 
             15 LOAD_ATTR                1 (call) 
             18 STORE_NAME               2 (foo) 
             21 LOAD_CONST               1 (None) 
             24 RETURN_VALUE         

If you're not familiar with the dis.dis output, here's a brief overview: The first column is the source line (since our sources' first lines are blank, the real code is on lines 2 and 3). The third column shows the bytecode instruction that is to be run, and the last column shows the arguments it receives. The other numbers are not important.

Now, not every Python bytecode takes the same amount of time to execute, but as a first approximation, comparing the number of instructions for each line of the two codes can suggest where they differ in performance.

The first version, which uses from ... import ... does a bunch more work during the import step. That is, it first imports the module, then loads the call attribute from it and saves that into the local namespace. This up front cost though pays off in the second step where we access the call function to save it into another variable. There's only one lookup required, since call is already in the top level namespace.

The second version that uses import ... does less up front work on the import line, but it must do two lookups to resolve subprocess.call in the second line.

So, we can conclude that if you are accessing an attribute many times, the from ... import ... approach will probably be faster. On the other hand, if you're only accessing the attribute once, using a plain import ... may have lower overhead.

But really, performance of imports is probably not a very important thing. Use whatever makes your code most readable, and worry about performance only if profiling tells you that you have a significant issue.

Upvotes: 1

sureshvv
sureshvv

Reputation: 4412

This kind of profiling is not useful since you do not have any code that uses the module that is being imported.

Include code that actually uses the subprocess module. You may find that the difference between the 2 types of imports to be of marginal consequence.

Upvotes: 1

Mark R. Wilkins
Mark R. Wilkins

Reputation: 1302

The reason for importing particular functions from modules is more about having manageable namespaces in your functions and less about speed. It is possible, as Joachim Pileborg suggests in your comments, that actual execution of the function brought in using from ... import is faster, but even then you may not notice the difference in the vast majority of scripts.

The best thing to do is import modules in the way that makes the code most readable and maintainable to you (for example, would you rather see call() or subprocess.call() in your code?) and focus on performance only in those specific instances where a small part of your code is a bottleneck, or your code is overall too slow.

Upvotes: 1

Mario Rossi
Mario Rossi

Reputation: 7799

In first place, any serious test requires more than 2 executions. But I assume you have performed many more with similar results.

What is improved is not import's time, but general execution time. Specifically the time it takes the interpreter to resolve any kind of symbols.

I'd suggest you to take the biggest module you have in production and replace all general imports with specific ones and time this.

Another reason to prefer specific imports is documentation: having an idea of what a program does and how it does it by its imports. If the imports are specific, this information is also more specific.

Upvotes: 1

Related Questions