Why do I need __init__.py at each level?

Given that I have the following directory structure, where . is the current working directory

 . \---foo \---bar \---__init__.py \---baz.py 

When I run python -c "import foo.bar.baz" , I get

 Traceback (most recent call last): File "<string>", line 1 ImportError: No module named foo.bar.baz 

If I echo "" > foo/__init__.py , the command above works.

Am I doing something wrong or misunderstanding the point __init__.py ? I thought this should stop existing modules where they shouldn't, for example. a directory called string , but if you replace foo with string in my example, I seem to be forced to create a module that should never be used, so I can reference the file deeper in the hierarchy.

Update

I work with a build system that generates __init__.py for me and provides a directory structure, and although I can mess around with the hierarchy, I would rather just add __init__.py myself. To slightly change the question, why do I need a python package at every level, and not just at the top? Is it just the rule that you can import modules only from the python path or from the package chain from the python path?

+5
source share
1 answer

Yes, this file is required if you want the directory to be treated as a module.

__init__.py files are required for Python to treat directories as containing packages; this is done to prevent directories with a common name, such as strings, from unintentionally hiding valid modules that appear later in the module search path. In the simplest case, __init__.py may just be an empty file, but it can also execute initialization code for the package or set the __all__ variable described below.

https://docs.python.org/3/tutorial/modules.html#packages

I am trying to create a nonempty __init__.py . You have a great opportunity to document the module in order to get rid of nested names for users / developers by providing the most useful objects (classes / functions) at the first level ...... in fact, to be as simple as possible to use in contrast - let let's say java import

Edit after updating question

Importers / crawlers by default (check sys.meta_path ):

  • BuiltinImporter - search / download built-in modules
  • FrozenImporter - search / load frozen modules (e.g. * .pyc)
  • PathFinder - the one that interests you allows you to search / download modules based on the file system

Thirdly, this is the __init__.py thing (actually FrozenImporter).

PathFinder looks for a module in paths from sys.path (and in __path__ defined in packages). A module can be either a stand-alone python file (if it is in the root of the search directory) or in 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 (pay attention to the parent module foo).

  • If you write your own finder (and bootloader), you can download, for example, any file you want, even though it is. It gives you great strength. For example, look at stack-overflow-import , exposing code based on SO search results.

+4
source

Source: https://habr.com/ru/post/1269489/


All Articles