Use 'import module' or 'from module import'?
The difference between import module
and from module import foo
is mainly subjective. Pick the one you like best and be consistent in your use of it. Here are some points to help you decide.
import module
- Pros:
- Less maintenance of your
import
statements. Don't need to add any additional imports to start using another item from the module
- Less maintenance of your
- Cons:
- Typing
module.foo
in your code can be tedious and redundant (tedium can be minimized by usingimport module as mo
then typingmo.foo
)
- Typing
from module import foo
- Pros:
- Less typing to use
foo
- More control over which items of a module can be accessed
- Less typing to use
- Cons:
- To use a new item from the module you have to update your
import
statement - You lose context about
foo
. For example, it's less clear whatceil()
does compared tomath.ceil()
- To use a new item from the module you have to update your
Either method is acceptable, but don't use from module import *
.
For any reasonable large set of code, if you import *
you will likely be cementing it into the module, unable to be removed. This is because it is difficult to determine what items used in the code are coming from 'module', making it easy to get to the point where you think you don't use the import
any more but it's extremely difficult to be sure.
There's another detail here, not mentioned, related to writing to a module. Granted this may not be very common, but I've needed it from time to time.
Due to the way references and name binding works in Python, if you want to update some symbol in a module, say foo.bar, from outside that module, and have other importing code "see" that change, you have to import foo a certain way. For example:
module foo:
bar = "apples"
module a:
import foo
foo.bar = "oranges" # update bar inside foo module object
module b:
import foo
print foo.bar # if executed after a's "foo.bar" assignment, will print "oranges"
However, if you import symbol names instead of module names, this will not work.
For example, if I do this in module a:
from foo import bar
bar = "oranges"
No code outside of a
will see bar
as "oranges" because my setting of bar
merely affected the name "bar" inside module a
, it did not "reach into" the foo
module object and update its bar
.
Even though many people already explained about import
vs import from
, I want to try to explain a bit more about what happens under the hood, and where all the places it changes are.
import foo
:
Imports foo
, and creates a reference to that module in the current namespace. Then you need to define completed module path to access a particular attribute or method from inside the module.
E.g. foo.bar
but not bar
from foo import bar
:
Imports foo
, and creates references to all the members listed (bar
). Does not set the variable foo
.
E.g. bar
but not baz
or foo.baz
from foo import *
:
Imports foo
, and creates references to all public objects defined by that module in the current namespace (everything listed in __all__
if __all__
exists, otherwise everything that doesn't start with _
). Does not set the variable foo
.
E.g. bar
and baz
but not _qux
or foo._qux
.
Now let’s see when we do import X.Y
:
>>> import sys
>>> import os.path
Check sys.modules
with name os
and os.path
:
>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
Check globals()
and locals()
namespace dicts with os
and os.path
:
>>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>
From the above example we found that only os
is inserted in the local and global namespace.
So, we should be able to use:
>>> os
<module 'os' from
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> os.path
<module 'posixpath' from
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>
But not path
.
>>> path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>
Once you delete the os
from locals() namespace, you won't be able to access os
as well as os.path
even though they exist in sys.modules:
>>> del locals()['os']
>>> os
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>
Now let's talk about import from
:
from
:
>>> import sys
>>> from os import path
Check sys.modules
with os
and os.path
:
>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
We found that in sys.modules
we found as same as we did before by using import name
OK, let's check how it looks like in locals()
and globals()
namespace dicts:
>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>
You can access by using name path
not by os.path
:
>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>
Let's delete 'path' from locals()
:
>>> del locals()['path']
>>> path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>
One final example using an alias:
>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>
And no path defined:
>>> globals()['path']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>