Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I import successfully without __init__.py?

Tags:

python

import

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?

like image 574
Poplong Avatar asked Jun 22 '16 17:06

Poplong


People also ask

Do you still need __ 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.

Why do I need __ init __ py?

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.

What would happen if __ init __ py file is not present in a Python package directory?

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.

Can I import from __ init __ py?

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.


2 Answers

__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.

like image 152
user2357112 supports Monica Avatar answered Oct 05 '22 02:10

user2357112 supports Monica


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.

like image 30
o11c Avatar answered Oct 05 '22 02:10

o11c