16

When in doubt, I typically place my import statements at the top of the module. Often, this cuts down on repetition, which is nice. Is there a performance downside, though, in the case where only a single function (or class) requires the import?

does the following only import when the function is called?

     def func():
         from task import test

If so, I imagine that might be a slight efficiency. I also assume that you could get some added points for faster garbage collection and variable scoping, since the imported objects would not be added to the global dictionary. As another poster nicely put it:

This is mostly due to variable look-up. Looking up a variable in the global scope requires a dictionary look-up. In contrast, the compiler determines local names statically and references them by index, so no dictionary look up is required.

Are those fair assumptions are am I totally off base?

Thanks

1
  • 2
    As for name lookup performance: It doesn't matter. In the rare case it does, you'll find out when you've finished the code, found out it's too slow, and profiled. Commented Jan 27, 2012 at 17:53

3 Answers 3

14

An import in a function is only imported when the function runs. Keep in mind that in Python, all statements are executed when they are encountered, and imports are statements like anything else. Top-level imports are imported when the module is imported, because they are top-level statements in the module.

Your concerns about name lookup are misguided: the difference is negligible, and should only be considered if profiling shows a problem.

I only import modules into function scope for two reasons: 1) to fix circular import problems, which btw likely could be solved in other ways by refactoring, or 2) if the module is optional, and the function isn't used by many of my users. In the case of 2), the module can be entirely missing, and there won't be a problem unless someone invokes the function.

Sign up to request clarification or add additional context in comments.

2 Comments

This was more of a theoretical question. Seems there is a difference, even if negligable. Thanks Ned
Is that the most pythonic way? I see some people make imports at init.py at the root of their module and import everything from there. Can that be used to solve certain circular imports?
5

Lets look at what the bytecode would look like for the following two functions:

def func1():
    """ test imported each time function is run """
    from task import test
    test()

def func2():
    """ test was imported at top of module """
    test()

As you can see below, func2() saves a lot of steps by using the globally imported test function.

>>> dis.dis(func1)
  3           0 LOAD_CONST               1 (-1)
              3 LOAD_CONST               2 (('test',))
              6 IMPORT_NAME              0 (task)
              9 IMPORT_FROM              1 (test)
             12 STORE_FAST               0 (test)
             15 POP_TOP

  4          16 LOAD_FAST                0 (test)
             19 CALL_FUNCTION            0
             22 POP_TOP
             23 LOAD_CONST               3 (None)
             26 RETURN_VALUE
>>> dis.dis(func2)
  3           0 LOAD_GLOBAL              0 (test)
              3 CALL_FUNCTION            0
              6 POP_TOP
              7 LOAD_CONST               1 (None)
             10 RETURN_VALUE

Taking this into account up front is probably premature optimization, as pointed out in delnan's comment.

As for test being in the global namespace, that is unlikely to cause any lookup performance issues. The most notable way I think you could see this is if there was a hash collision for test and another name that you use very often, which caused the lookup of that second name to take longer. Again, premature optimization to consider that rare case up front.

2 Comments

But note that it won't actually import the module more than once - it just checks whether is has to each time it's called.
Thanks for laying it out like this; it's useful. Was not familiar with the dis library.
0

I think it makes sense to put the import in the definition if it is not going to be called very often.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.