Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why should I use __all__ in __init__ of python package?

Tags:

python

package

I've already read Can someone explain __all__ in Python? and I understand that it only affects from ... import * statements, but I can't figure out a real use case. Why should I repeat exported names in __all__ (DRY!) when I could simply avoid importing those names in __init__ namespace?

Example:

mypackage/__init__.py

from a import A

mypackage/a.py

A = "A"
A1 = "A1"

mypackage/b.py

B = "B"    

And then in python:

>>> from mypackage import *
>>> A
'A'
>>> 
>>> A1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'A1' is not defined
>>> b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined

As you can see A is in the namespace but A1 and b are not. Why should I have to define __all__ = ["A"]?

like image 276
Zac Avatar asked Jun 17 '15 10:06

Zac


1 Answers

The only time you want to define __all__ in your package's __init__.py is to list the names of "exported" members that you want to export for when a user does:

from package import *

This is documented in 6.4.1. Importing * From a Package

Note: If you don't define an __all__ in your package then the default behaviour is as follows (from the documentation):

If __all__ is not defined, the statement from sound.effects import * does not import all submodules from the package sound.effects into the current namespace; it only ensures that the package sound.effects has been imported (possibly running any initialization code in __init__.py) and then imports whatever names are defined in the package. This includes any names defined (and submodules explicitly loaded) by __init__.py. It also includes any submodules of the package that were explicitly loaded by previous import statements. Consider this code:

A "naive" interpretation of this can be:

If you don't define __all__; a from package import * will bring in everything from that package and anything imported in that pacakge's __init__.py.

like image 60
James Mills Avatar answered Oct 17 '22 10:10

James Mills