Package-level exports, circular dependencies

Viewed 99

I have the following package:

foo/
    __init__.py:
        from .body import UsefulClass
        from .another import AnotherClass

    body.py:

        from . import utll
        class UsefulClass:
            util.do_something()

    another.py:

        class AnotherClass: ...

    util.py:

        def do_something...

   

The idea is, when someone imports foo, they should be able to use foo.UsefulClass without worrying about the internal structure of the package. In other words, I don't want them to import foo.body, just foo.

However, when I do from . import util in body.py this also imports __init__.py, which in turn imports body once again. I realize that python handles this situation well, however I'm not comfortable having this obviously circular dependency.

Is there a better way to export things at the package level without creating circular dependencies in imports?

PS: I'd like to avoid in-function imports

1 Answers

I think your initial premise is wrong. If you do an import foo statement with your current setup, __init__.py and body.py will only be imported once as can be shown by putting a print statement as the first line in each of those files:

The layout of directory foo (I have omitted another.py, since its presence or absence is not relevant):

enter image description here

File __init__.py:

print('__init__.py imported')

from .body import UsefulClass

File body.py:

print('body.py imported')

from . import util

class UsefulClass:
    x = util.do_something()

File util.py:

def do_something():
    return 9

And finally:

Python 3.8.5 (tags/v3.8.5:580fbb0, Jul 20 2020, 15:57:54) [MSC v.1924 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo
__init__.py imported
body.py imported
>>> foo.UsefulClass.x
9
>>>
Related