Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clarification about Python imports

What's the difference between from foo import barand import foo.bar as bar?

Is there any difference as far as Python namespaces and scope are concerned? If you want to use something from bar (say a function called whatever), you'd call it as bar.whatever() using either approach.

I see both styles of imports in a code base I'm working with and was wondering what differences they entail, if any, and what would be considered the more "Pythonic" approach.

like image 406
akshayc Avatar asked Aug 12 '16 18:08

akshayc


2 Answers

There is a difference, both for when there is a bar module or package inside the foo package, and if bar is not a module at all.

Considered the following foo package:

foo/
    __init__.py
    bar.py

If the __init__.py file defines a global name bar too, then the first example will import that object. The second example will import the bar.py module.

However, once the foo.bar module has been imported, the Python import machinery will set the name bar in the foo package, replacing any pre-existing bar global in __init__.py:

$ ls -1 foo/
__init__.py
bar.py
$ cat foo/__init__.py
bar = 'from the foo package'
$ cat foo/bar.py
baz = 'from the foo.bar module'
$ python
Python 2.7.12 (default, Aug  3 2016, 18:12:10)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from foo import bar
>>> bar
'from the foo package'
>>> import foo.bar as bar
>>> bar
<module 'foo.bar' from 'foo/bar.pyc'>
>>> bar.baz
'from the foo.bar module'
>>> from foo import bar
>>> bar
<module 'foo.bar' from 'foo/bar.pyc'>

The other case is where there is no bar.py submodule. foo could either be a package, or a simple module. In that case from foo import bar will always look for an object in the foo module, and import foo.bar as bar will always fail:

$ cat foo.py
bar = 'from the foo module'
$ python
Python 2.7.12 (default, Aug  3 2016, 18:12:10)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo
>>> foo.bar
'from the foo module'
>>> from foo import bar
>>> bar
'from the foo module'
>>> import foo.bar as bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named bar

Note that in all cases where the import succeeds, you end up with a global name bar bound to something, either an object from a module, or a module object.

like image 89
Martijn Pieters Avatar answered Sep 26 '22 08:09

Martijn Pieters


When bar is not a module, there is a huge difference:

# foo.py
bar = object()

Here from foo import bar would be normal in python, but import foo.bar as bar would raise an ImportError: No module named bar.

Usually we only use the "as" construct to alias a name: either for adding some context to the name to improve readability, or to avoid a clash with another name.

like image 42
wim Avatar answered Sep 24 '22 08:09

wim