Is __init__.py not required for packages in Python 3.3+
Python 3.3+ has Implicit Namespace Packages that allow it to create a packages without an __init__.py
file.
Allowing implicit namespace packages means that the requirement to provide an
__init__.py
file can be dropped completely, and affected ... .
The old way with __init__.py
files still works as in Python 2.
What is __init__.py for?
It used to be a required part of a package (old, pre-3.3 "regular package", not newer 3.3+ "namespace package").
Here's the documentation.
Python defines two types of packages, regular packages and namespace packages. Regular packages are traditional packages as they existed in Python 3.2 and earlier. A regular package is typically implemented as a directory containing an
__init__.py
file. When a regular package is imported, this__init__.py
file is implicitly executed, and the objects it defines are bound to names in the package’s namespace. The__init__.py
file can contain the same Python code that any other module can contain, and Python will add some additional attributes to the module when it is imported.
But just click the link, it contains an example, more information, and an explanation of namespace packages, the kind of packages without __init__.py
.
Is __init__.py required for every python package? [new feature since python 3.3+]
Python 3.3+ has implicit namespace packages that allow you to create packages without __init__.py
. In Python 2, __init__.py
is the old method and still works.
Allowing implicit namespace packages means that the requirement to provide an __init__.py file can be dropped completely, and affected portions can be installed into a common directory or split across multiple directories as distributions see fit.
Note: init.py files were used to mark directories on your disk as Python packages.
Useful links:
- Implicit Namespace Packages
Why do I need __init__.py at every level?
Yes, this file is required if you want directory to be treated as a module.
The
__init__.py
files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case,__init__.py
can just be an empty file, but it can also execute initialization code for the package or set the__all__
variable, described later.
https://docs.python.org/3/tutorial/modules.html#packages
In a __init__.py
file you have great possibility to document module, to get rid of the nested imports for a user/developer by providing the most useful objects(classes/functions) at the first level... ...actually to be as simple in use as possible.
Edit after question update
The default importer/finder (examine the sys.meta_path
) is:
- BuiltinImporter - searches for/load a built-in module
- FrozenImporter - searches for/loads frozen module (e.g. *.pyc)
- PathFinder - the one you are interested in, allow to search for/loads a module based on the file system
The third is the __init__.py
thing (actually the FrozenImporter
as well).
ThePathFinder
searches for a module in the paths from sys.path
(and in __path__
defined in a package). The module could be either a standalone python file (if it is in the root of the search path) or a directory with __init__.py
.
Referring to your example:
foo/
bar/
__init__.py
baz.py
If you create
__init__.py
infoo/
,foo.bar.baz
will be available (as you said).If you add
foo/
tosys.path
or pass it throughPYTHONPATH=foo/
,bar.baz
will be available (note without parent modulefoo
).If you write your own finder (and loader) you can load for example any file you want despite where it is. That gives you great power. For example take a look on
stack-overflow-import
, exposes code based on SO's search results.
Python - why can I import modules without __init__.py at all?
I think this is a good 'answer' for what I didn't understand.
myMath/
__init__.py
adv/
__init__.py
sqrt.py
fib.py
add.py
subtract.py
multiply.py
divide.py
myMath/__init__.py
from add import add
from divide import division
from multiply import multiply
from subtract import subtract
from adv.fib import fibonacci
from adv.sqrt import squareroot
index.py
import sys
sys.path.append('C:\Users\mdriscoll\Documents')
import mymath
print mymath.add(4,5)
print mymath.division(4, 2)
print mymath.multiply(10, 5)
print mymath.fibonacci(8)
print mymath.squareroot(48)
Imports inside package now that __init__.py is optional
The missing __init__.py
are not the problem - you are using outdated relative imports.
import sub.module # implicit relative import - py2 only
from . import sub.module # explicit relative import
Note that a .
import always requires the from .<where> import <name>
form. It would not produce a valid name otherwise. The following should work, assuming your run script.py
via python3 -m src.script
- an IDE will likely do the same.
from . import sub.module
from .sub import module
from .sub.module import *
from . import parent_module
If you are running as plain python3 script.py
or python3 -m script
, you cannot use relative imports. Only absolute imports will work in this case.
import sub.module
from sub import module
from sub.module import *
import parent_module
While you do not need __init__.py
files, it is a good idea to add them if your package is not a namespace. Otherwise, other similarly constructed packages of the same name may be inserted into yours.
why does python require __init__.py to treat directories as containing packages?
Lets say you had a project that contained a directory called math
that contained some numerical data. If no __init__.py
were required, then when you did import math
, it would try to import that directory instead of the real math
module. But since your directory just contained data and not actual Python code, the import would fail. Thus your math
directory would block you from importing the real math
module from the standard library, even though your math
directory doesn't contain Python code at all.
The __init__.py
is like a confirmation, the directory saying "Yes, I really am a Python package, not just a directory full of files. It makes sense to import me." Any directories that don't "announce" themselves in this way are skipped over because Python knows they can't be imported. This is good, because the Python standard library has modules with lots of common names (os, math, time, symbol, resource, etc.). Without the __init__.py
requirement, you would never be able to use any of those names for any directory on your Python path -- not even to store data or files unrelated to Python.
string
is actually not the best example in this case. There is a module called string
but it is not so useful these days because most of its functions are available as methods on the str
type. But, like I mentioned, there are lots of other modules with common names.
Related Topics
Tensorflow Install Fails with "Compiletime Version 3.5 of Module Does Not Match Runtime Version 3.6"
How to Upload File with Python Requests
Is _Init_.Py Not Required for Packages in Python 3.3+
What's the Best Way to Parse a JSON Response from the Requests Library
Runtimeerror on Windows Trying Python Multiprocessing
How to Call a Python Function from Node.Js
How to Convert a Nested Python Dict to Object
From List of Integers, Get Number Closest to a Given Value
Find All Occurrences of a Key in Nested Dictionaries and Lists
Set Bash Variable from Python Script
Detect Specific Keypresses in Gui
How to "Perfectly" Override a Dict
I Can't Install Pyaudio on Windows? How to Solve "Error: Microsoft Visual C++ 14.0 Is Required."
Read Specific Columns from a CSV File with CSV Module