from ... import
vs. import
Always avoid wildcard imports like such:
1 | from my_module import * # don't use this |
Instead, use regular import like:
1 | import my_module # use this |
Why?
- using wildcard import will pollute namespaces
- Using wildcard import will not import names with a leading underscore (unless the module defines an
__all__
list) - PEP8 recommend using regular import
What does __init__.py
do?
-
__init__.py
is used to specify a package, when import is trying to find the modules, But it is not required: meaning a package without__init__.py
, The system can still find the modules after configuring appropriatePYTHONPATH
usingsys.path.append
. -
__init__.py
is executed after importing the package, I’ve seen sub-directory being imported by appending as environment variable within__init__.py
Example:
so instead of using import project.foo.bar
for the following structure:
1 | project/ |
inside the __init__.py
, we could do a sys.path.append(PATH_TO_BAR)
so with this file structure, we can just do import project
they could even add the import statement for us in the __init__.py
, although it is not transparent.
1 | project/ |
Note: Whatever gets appended last overrides the previous env variable, so import to the same name module will find the latest append
Dot Notation (.
) in Import
1 | parent/ |
Each dot in our import will refer to something inside the package, could be another package or a module. But it can’t be a class.
Import python modules could look like:
import parent.file
or import parent.one.anotherfile
From … import classes or functions look like this:
from parent.file import class
which gives us direct access to the class namespace, but not the example above.
Import Order
Based on PEP8, imports should be grouped by the following order:
- Standard library import
- Related third-party import
- Local application/library specific import
What is Standard Library Imports?
Standard library are installed automatically by Python installer, full documentation link is here: https://docs.python.org/3/library/
What is the order after grouping?
There is no specific rules, but based on common preferences, use alphabetical order, with import first and from … import after
1 | import abc |
Intra-package
In a structure like this, how would you do import from another directory?
say from module-x.py
import module-a
1 | top-package/ |
Here’s some examples doing relative imports in module-x
1 | import module-y |
Import an import
It is a common practice in C#
to use import module or static class to stores all the global variables
used for settings, or even all the modules. In Python it would be something like:
constant.py
1 | import module_a |
With this setup, all the module in the same project would just import the constant
module and have access to
all the imports and variable. I thought this was a neat way to make code cleaner by getting rid of all the duplicated imports
that might happen.
there are also some voices against it:
- based on the style guide: Constants are usually defined on a module level
- also, suggestions have mentioned to refrain from using class as it could be instantiated which makes no sense.
- unless there’s a valid reason for all those modules to be collected under a common name. If not, then they should be kept separately. This is due to documentation, as other people open our file, they don’t get information on what is getting imported (what is needed)
Same module import multiple times
So if multiple files are importing the same module separately, does python optimize the import?
Yes, python modules are considered as singletons, no matter how many times we import them they get initialized only once. unless reload is being called
Reference
Stack Overflow - constants in Python: at the root of the module or in a namespace inside the module?
Stack Overflow - in python, do you need to import modules in each split file?
Stack Overflow - Python: Importing an “import file”
Stack Overflow - Does python optimize modules when they are imported multiple times?
Stack Overflow - Why can I import successfully without init.py?
Stack Overflow - relative path not working even with init.py