What exactly is the use of __init__.py
? Yes, I know this file makes a directory into an importable package. However, consider the following example:
project/
foo/
__init__.py
a.py
bar/
b.py
If I want to import a
into b
, I have to add following statement:
sys.path.append('/path_to_foo')
import foo.a
This will run successfully with or without __init__.py
. However, if there is not an sys.path.append
statement, a "no module" error will occur, with or without __init__.py
. This makes it seem lik eonly the system path matters, and that __init__.py
does not have any effect.
Why would this import work without __init__.py
?
The __init__.py file indicates that the files in a folder are part of a Python package. Without an __init__.py file, you cannot import files from another directory in a Python project.
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.
If you remove the __init__.py file, Python will no longer look for submodules inside that directory, so attempts to import the module will fail.
There are two types of packages in python, regular and namespace packages. The former requires __init__.py file whereas the latter does not. Any directory with an init python file is marked as a package by python and can be imported.
__init__.py
has nothing to do with whether Python can find your package. You've run your code in such a way that your package isn't on the search path by default, but if you had run it differently or configured your PYTHONPATH
differently, the sys.path.append
would have been unnecessary.
__init__.py
used to be necessary to create a package, and in most cases, you should still provide it. Since Python 3.3, though, a folder without an __init__.py
can be considered part of an implicit namespace package, a feature for splitting a package across multiple directories.
During import processing, the import machinery will continue to iterate over each directory in the parent path as it does in Python 3.2. While looking for a module or package named "foo", for each directory in the parent path:
- If
<directory>/foo/__init__.py
is found, a regular package is imported and returned.- If not, but
<directory>/foo.{py,pyc,so,pyd}
is found, a module is imported and returned. The exact list of extension varies by platform and whether the -O flag is specified. The list here is representative.- If not, but
<directory>/foo
is found and is a directory, it is recorded and the scan continues with the next directory in the parent path.- Otherwise the scan continues with the next directory in the parent path.
If the scan completes without returning a module or package, and at least one directory was recorded, then a namespace package is created.
If you really want to avoid __init__.py
for some reason, you don't sys.path
. Rather, create a module object and set its __path__
to a list of directories.
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