Is _Init_.Py Not Required for Packages in Python 3.3+

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:

  1. 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:

  1. BuiltinImporter - searches for/load a built-in module
  2. FrozenImporter - searches for/loads frozen module (e.g. *.pyc)
  3. 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 in foo/, foo.bar.baz will be available (as you said).

  • If you add foo/ to sys.path or pass it through PYTHONPATH=foo/, bar.baz will be available (note without parent module foo).

  • 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



Leave a reply



Submit