There are two issues here. The first step is to figure out which part is faster: the import statement, or the call.
So, let's do that:
$ python -mtimeit 'import math'
1000000 loops, best of 3: 0.555 usec per loop
$ python -mtimeit 'from math import sqrt'
1000000 loops, best of 3: 1.22 usec per loop
$ python -mtimeit -s 'from math import sqrt' 'sqrt(10)'
10000000 loops, best of 3: 0.0879 usec per loop
$ python -mtimeit -s 'import math' 'math.sqrt(10)'
10000000 loops, best of 3: 0.122 usec per loop
(That's with Apple CPython 2.7.2 64-bit on OS X 10.6.4 on my laptop. But python.org 3.4 dev on the same laptop and 3.3.1 on a linux box give roughly similar results. With PyPy, the smarter caching makes it impossible to test, since everything finishes in 1ns… Anyway, I think these results are probably about as portable as microbenchmarks ever can be.)
So it turns out that the import
statement is more than twice as fast; after that, calling the function is a little slower, but not nearly enough to make up for the cheaper import
. (Keep in mind that your test was doing an import
for each call. In real-life code, of course, you tend to call things a lot more than once per import
. So, we're really looking at an edge case that will rarely affect real code. But as long as you keep that in mind, we proceed.)
Conceptually, you can understand why the from … import
statement takes longer: it has more work to do. The first version has to find the module, compile it if necessary, and execute it. The second version has to do all of that, and then also extract sqrt
and insert it into your current module's globals. So, it has to be at least a little slower.
If you look at the bytecode (e.g., by using the dis
module and calling dis.dis('import math')
), this is exactly the difference. Compare:
0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (math)
9 STORE_NAME 0 (math)
12 LOAD_CONST 1 (None)
15 RETURN_VALUE
… to:
0 LOAD_CONST 0 (0)
3 LOAD_CONST 1 (('sqrt',))
6 IMPORT_NAME 0 (math)
9 IMPORT_FROM 1 (sqrt)
12 STORE_NAME 1 (sqrt)
15 POP_TOP
16 LOAD_CONST 2 (None)
19 RETURN_VALUE
The extra stack manipulation (the LOAD_CONST
and POP_TOP
) probably doesn't make much difference, and using a different argument to STORE_NAME
is unlikely to matter at all… but the IMPORT_FROM
is a significant extra step.
Surprisingly, a quick&dirty attempt to profile the IMPORT_FROM
code shows that the majority of the cost is actually looking up the appropriate globals to import into. I'm not sure why, but… that implies that importing a whole slew of names should be not much slower than importing just one. And, as you pointed out in a comment, that's exactly what you see. (But don't read too much into that. There are many reasons that IMPORT_FROM
might have a large constant factor and only a small linear one, and we're not exactly throwing a huge number of names at it.)
One last thing: If this ever really does matter in real code, and you want to get the best of both worlds, import math; sqrt = math.sqrt
is faster than from math import sqrt
, but gives you the same small speedup to lookup/call time. (But again, I can't imagine any real code where this would matter. The only time you'll ever care how long sqrt
takes is when you're calling it a billion times, at which point you won't care how long the import takes. Plus, if you really do need to optimize that, create a local scope and bind sqrt
there to avoid the global lookup entirely.)