Suppose I have a module rules
with the following structure:
rules ├── conditions.py ├── __init__.py
In the script conditions.py
, I'd like to import a class called RuleParserError
defined in __init__.py
. However, I haven't been able to figure out how to do this. (Following Python: How to import from an __init__.py file? I've tried
from . import RuleParserError
but this leads to an ImportError: cannot import name RuleParserError
when trying to run conditions.py
as __main__
).
Python use a variable called PYTHPATH to search modules. If a directory is not in the PYTHONPATH and isn't current directory(or sub directory) of the input script,you cann't import files in this folder. So, if we want to import a file in the different folder, we should add the folder to the PYTHONPATH first.
We can use sys. path to add the path of the new different folder (the folder from where we want to import the modules) to the system path so that Python can also look for the module in that directory if it doesn't find the module in its current directory.
In addition to labeling a directory as a Python package and defining __all__ , __init__.py allows you to define any variable at the package level. Doing so is often convenient if a package defines something that will be imported frequently, in an API-like fashion.
path looking for the package subdirectory. The __init__.py files are required to make Python treat directories containing the file as packages. This prevents directories with a common name, such as string , unintentionally hiding valid modules that occur later on the module search path.
I see 'import from parent module' as an anti-pattern in Python. Imports should be the other way around. Importing from modules's __init__.py
is especially problematic. As you noticed, importing module foo.bar
from foo/bar.py
involves importing foo/__init__.py
first, and you may end up with a circular dependency. Adding a print("Importing", __name__)
to your init files helps see the sequence and understand the problem.
I'd suggest that you moved the code you want to import in conditions.py
from __init__.py
to a separate lower-level module, and just import some names from that module in __init__.py
to expose it at higher level.
Let's suppose that you had some class Bar
in your __init__.py
. I'd reorganize it the following way.
__init__.py
:
from bar import Bar # exposed at the higher level, as it used to be.
bar.py
:
class Bar(object): ...
conditions.py
:
from . import Bar # Now it works.
Ideally an __init__.py
should contain nothing but imports from lower-level modules, or nothing at all.
If you get
ImportError: attempted relative import with no known parent package
when you do like
import . from something
especially from the script executed, just try
from __init__ import something
Even though it could be problematic when there are many __init__.py
s in sys.path
, it would be helpful in some simple situaions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With