In Python, what happens when you import inside of a function?
No; or rather, Python modules are essentially cached every time they are imported, so importing a second (or third, or fourth...) time doesn't actually force them to go through the whole import process again. 1Does it re-import every time the function is run?
No, it is only imported if and when the function is executed. 2, 3Does it import once at the beginning whether or not the function is run?
As for the benefits: it depends, I guess. If you may only run a function very rarely and don't need the module imported anywhere else, it may be beneficial to only import it in that function. Or if there is a name clash or other reason you don't want the module or symbols from the module available everywhere, you may only want to import it in a specific function. (Of course, there's always from my_module import my_function as f
for those cases.)
In general practice, it's probably not that beneficial. In fact, most Python style guides encourage programmers to place all imports at the beginning of the module file.
Is it pythonic to import inside functions?
In the long run I think you'll appreciate having most of your imports at the top of the file, that way you can tell at a glance how complicated your module is by what it needs to import.
If I'm adding new code to an existing file I'll usually do the import where it's needed and then if the code stays I'll make things more permanent by moving the import line to the top of the file.
One other point, I prefer to get an ImportError
exception before any code is run -- as a sanity check, so that's another reason to import at the top.
I use pyChecker
to check for unused modules.
Should import statements always be at the top of a module?
Module importing is quite fast, but not instant. This means that:
- Putting the imports at the top of the module is fine, because it's a trivial cost that's only paid once.
- Putting the imports within a function will cause calls to that function to take longer.
The best reasons I've seen to perform lazy imports are:
- Optional library support. If your code has multiple paths that use different libraries, don't break if an optional library is not installed.
- In the
__init__.py
of a plugin, which might be imported but not actually used. Examples are Bazaar plugins, which usebzrlib
's lazy-loading framework.
If I import a module inside a function, will the variables be local?
Yes, the module will be local to the function, at least in the example above(I am using Python 3.6).
Example:
Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
def test():
... import math
... s = math.cos(1)
...
g = math.cos(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'math' is not defined
Import statement inside class/function definition - is it a good idea?
It's the most common style to put every import at the top of the file. PEP 8 recommends it, which is a good reason to do it to start with. But that's not a whim, it has advantages (although not critical enough to make everything else a crime). It allows finding all imports at a glance, as opposed to looking through the whole file. It also ensures everything is imported before any other code (which may depend on some imports) is executed. NameError
s are usually easy to resolve, but they can be annoying.
There's no (significant) namespace pollution to be avoided by keeping the module in a smaller scope, since all you add is the actual module (no, import *
doesn't count and probably shouldn't be used anyway). Inside functions, you'd import again on every call (not really harmful since everything is imported once, but uncalled for).
import inside a function: is memory reclaimed upon function exit?
The first import executes the code in the module. It creates the module object's attributes. Each subsequent import just references the module object created by the first import.
Module objects in Python are effectively singletons. For this to work, the Python implementation has to keep the one and only module instance around after the first import, regardless of the name the module was bound to. If it was bound to a name anyway, as there are also imports of the form from some_module import some_name
.
So no, the memory isn't reclaimed.
No idea about Micropython, but I would be surprised if it changes semantics here that drastically. You can simply test this yourself:
some_module.py:
value = 0
some_other_module.py:def f():
import some_module
some_module.value += 1
print(some_module.value)
f()
f()
This should print the numbers 1 and 2. Advantage of importing libraries inside function?
Actually, importing the modules locally inside a function would improve efficiency (slightly). Looking up local names is always faster than looking up globals because the global namespace is one of the last that Python checks when searching for a name.
That said, I wouldn't recommend doing this for three reasons:
It wastes lines of code. Every function which needs a particular module will have to import it. This means that you will have a lot of repeated import statements.
It makes the dependencies of your code hard to find. One of the main reasons that you import at the top of a file is so that the imports are easily visible.
It goes against PEP 0008, which specifically says:
Imports are always put at the top of the file, just after any module
comments and docstrings, and before module globals and constants.
Is there a performance cost putting python imports inside functions?
The point at which you import a module is not expected to cause a performance penalty, if that's what you're worried about. Modules are singletons and will not be import
ed every single time an import
statement is encountered. However, how you do the import, and subsequent attribute lookups, does have an impact.
For example, if you import math
and then every time you need to use the sin(...)
function you have to do math.sin(...)
, this will generally be slower than doing from math import sin
and using sin(...)
directly as the system does not have to keep looking up the function name within the module.
This lookup-penalty applies to anything that is accessed using the dot .
and will be particularly noticeable in a loop. It's therefore advisable to get a local reference to something you might need to use/invoke frequently in a performance critical loop/section.
For example, using the original import math
example, right before a critical loop, you could do something like this:
# ... within some function
sin = math.sin
for i in range(0, REALLY_BIG_NUMBER):
x = sin(i) # faster than: x = math.sin(x)
# ...
This is a trivial example, but note that you could do something similar with methods on other objects (e.g. lists, dictionaries, etc).I'm probably a bit more concerned about the circular imports you mention. If your intention is to "fix" circular imports by moving the import statements into more "local" places (e.g. within a specific function, or block of code, etc) you probably have a deeper issue that you need to address.
Personally, I'd keep the imports at the top of the module as it's normally done. Straying away from that pattern for no good reason is likely to make your code more difficult to go through because the dependencies of your module will not be immediately apparent (i.e. there're import
statements scattered throughout the code instead of in a single location).
It might also make the circular dependency issue you seem to be having more difficult to debug and easier to fall into. After all, if the module is not listed above, someone might happily think your module A
has no dependency on module B
and then up adding an import A
in B
when A
already has import B
hidden in some deep dark corner.
Benchmark Sample
Here's a benchmark using the lookup notation:
>>> timeit('for i in range(0, 10000): x = math.sin(i)', setup='import math', number=50000)
89.7203312900001
And another benchmark not using the lookup notation:>>> timeit('for i in range(0, 10000): x = sin(i)', setup='from math import sin', number=50000)
78.27029322999988
Here there's a 10+ second difference.Note that your gain depends on how much time the program spends running this code --i.e. a performance critical section instead of sporadic function calls.
Importing a function inside another function
A nested function function_2
is an object in the local namespace of the outer function. It doesn't even exist as a function when function_1
is not running.
Normally, a nested function either performs a private computation for the outer function, or gets returned in some form or another. In the latter case, you can run function_1
to get a reference to function_2
.
Any object that you want to import should be in the global namespace, or at least directly referenceable from it. A better design would be
x = 3
def function_1(x):
y = x + 7
# Do some stuff, including using function_2
return y
def function_2(value):
# Do some stuff
return value
And keep in mind that defining a function is not the same as running it. As a corollary, the x
inside function_1
is not the same as the x
that you set to 3 at the module level.Update for your update
You absolutely can make function_1
into a class, and make function_2
a method of it:
class function_1:
def __call__(self, x):
y = x + 7
value = self.function_2(y)
return y, value
@staticmethod
def function_2(value):
return value
In this case you could do the following in your other script:from test import function_1
f1 = function_1()
# Call it:
f1(7)
# Call function_2:
function_1.function_2('blah')
# Or alternatively:
f1.function_2('foo')
Importing modules that have all its functions inside a main() function
main()
typically calls your other functions but does not contain them. Your other functions will lie in the body of the script above main()
and can be called in the standard way.
So your test.py
example could look like this:
def my_function():
print('Hello')
def my_function2(num):
return num*num
def main():
my_function()
my_function2(5)
if __name__ == "__main__": # if module not imported
main()
Related Topics
Find the Date for the First Monday After a Given Date
How to Have Shared Log Files Under Windows
Possible Values from Sys.Platform
How to Avoid Infinite Recursion with Super()
Python Using Variables from Another File
Safely Create a File If and Only If It Does Not Exist with Python
Is It Bad Practice to Use a Built-In Function Name as an Attribute or Method Identifier
Errors While Building/Installing C Module for Python 2.7
Animated Subplots Using Matplotlib
How to Change Data Points Color Based on Some Variable
Python - Datetime with Timezone to Epoch
Pandas Number Rows Within Group in Increasing Order
How to Read a File Line-By-Line in Python
Source Interface with Python and Urllib2
SQL Alchemy Orm Returning a Single Column, How to Avoid Common Post Processing