MartyMacGyver MartyMacGyver - 1 month ago 10
Python Question

Importing a module in Python as part of a package *as well* as in a way that works stand-alone

Note: This is Python 3.5

Given some project

thing
such that:

thing/
top.py (imports bar)
utils/
__init__.py (empty)
bar.py (imports foo; has some functions and variables)
foo.py (has some functions and variables)


I can
import utils.bar
in top.py, and when running top.py the file bar.py must contain
import utils.foo
to get to foo.py's code.

To run bar.py directly though, bar.py must have
import foo
instead (
import utils.foo
fails). If I make that change then top.py no longer works.

How can I run top.py or bar.py and still use the same import construct in bar.py for both use cases? I feel like I'm missing some simple step or construct, but perhaps expecting bar.py to work independently in this way is asking too much (short of conditional imports or such).

Answer

Its typical to have all your entrypoints outside the module, than all imports can be relative. For example

thing/
    app.py
    thing/
        __init__.py
        top.py
        utils/
            __init__.py
            bar.py
            foo.py

And app.py can look like

from thing import app
if __name__ == '__main__':
    app.main()

Than in top.py you have

from .utils import bar

And in bar you have

from . import foo

Or

from thing.utils import foo

Or

from ..utils import foo

So if you need two entrypoints, you can either make app take a command line argument for the second entry point, or you can make another file like app that imports bar