Effective Python Item 50: Use Packages to Organize Modules and Provide Stable APIs
Python can limit the “interface” exposed to API consumers who use
import * by defining the
__all__ special attribute of a module or package.
~~~~~ 2017-11-16 补充开始 ~~~~~
__all__doesn’t prevent any of the module symbols (functions, classes, etc.) from being directly imported. In our the example, the seemingly omitted
bazfunction (which is not included in
__all__), is still perfectly importable by writing
from module import baz.
__all__doesn’t influence what symbols are included in the results of
vars(module). So in the case above, a
dircall would result in a
['Foo', 'bar', 'baz']list, even though
'baz'does not occur in
In other words, the content of
__all__is more of a convention rather than a strict limitation. Regardless of what you put there, every symbol defined in your module will still be accessible from the outside.
This is a clear reflection of the common policy in Python: assume everyone is a consenting adult, and that visibility controls are not necessary.
~~~~~ 2017-11-16 补充结束 ~~~~~
__all__ in a module
When consuming code does
from foo import *, only the attributes in
foo.__all__ will be imported from
__all__ isn’t present in
foo, then only public attributes, those without a leading underscore, are imported.
# foo.py __all__ = ['Foo'] class Foo(object): pass
__all__ for a package
To do this with package
mypackage, you need to modify the
__init__.py file in the
mypackage directory. This file actually becomes the contents of the
mypackage module when it’s imported. Thus, you can specify an explicit API for
mypackage by limiting what you import into
mypackage directory structure is:
mypackage ├── __init__.py ├── model.py └── util.py
__all__ are defined in
Since all of my internal modules already specify
__all__, I can expose the public interface of
mypackage by simply importing everything from the internal modules and updating
# __init__.py __all__ =  from .models import * __all__ += models.__all__ from .utils import * __all__ += utils.__all__
from .xxx (no space between
xxx) means relative import, i.e. importing from a relative path.
Guido has Pronounced that relative imports will use leading dots. A single leading dot indicates a relative import, starting with the current package. Two or more leading dots give a relative import to the parent(s) of the current package, one level per dot after the first.
Also note that you can also
from . import xxx to relatively import the whole module