0xC0000022L
0xC0000022L

Reputation: 21319

What are the rules for __all__ and relative imports?

Inside a package I am using a few checks inside each module directory's __init__.py to see whether the environment is sane and then use from . import mod1 for nested modules (mod1 here). Each of the module directories in turn contains an __init__.py (obviously) which will import the next lower level (if any).

Some of the __init__.py contain __all__ arrays to only expose certain names upon import.

Let's say I have the following "main" script (spam.py):

import os, sys

if (sys.version_info[0] != 2) or (sys.version_info < (2,7)):
    sys.exit("...")
else:
    import pkgname

def main():
    pass

if __name__ == '__main__':
    main()

and the following pkgname/__init__.py:

import sys
if __name__ == '__main__':
    sys.exit(0)
else:
    from . import db
    from os.path import dirname, realpath
    sys.modules[__name__].__all__ = ['inipath']
    sys.modules[__name__].__dict__['inipath'] = dirname(realpath(__file__)) + '.ini'

and the following pkgname/db/__init__.py:

import sys
if __name__ == '__main__':
    sys.exit(0)
else:
    import sqlite3
    # ...
foobar = { 'spam' : 'egg' }

__all__ = ["foobar"]

will the symbol pkgname.db.foobar be visible despite the __all__ array in pkgname/__init__.py? I.e. does the __all__ array only affect the immediate module or also any lower level?

Which rules govern Python's behavior here? I tried some searches but came up empty-handed. Possibly I used the wrong searches (__all__, python, relative import)?

Upvotes: 1

Views: 537

Answers (1)

BrenBarn
BrenBarn

Reputation: 251518

__all__ has no effect in the case you're describing. It only affects what happens when you do from package import *. See the documentation as well as previous questions (which I found by googling python __all__).

Upvotes: 4

Related Questions