mariogarcc
mariogarcc

Reputation: 388

Importing modules from parent package

I have a structure like the following:

package/
    setup.py
    ...
    package/
        __init__.py
        _foo.py
        subpackage/
            __init__.py
            bar.py

I am trying to import _foo from inside bar:

# bar.py
from .._foo import baz

def myfunc():
    baz()
    # stuff

while running bar.py as a script (for example, in a Jupyter Notebook, or even with python bar.py. If I run this as a module using python -m package.subpackage.bar it works, but I want to find ways around this). I can't get it to work:

>>> from . import _foo
ImportError: cannot import name '_foo' from '__main__' (unknown location)
# changing __name__ to 'package' doesn't work etiher
>>> from ._foo import baz
ModuleNotFoundError: No module named '__main__._foo'; '__main__' is not a package
>>> from .. import _foo
ValueError: attempted relative import beyond top-level package

>>> sys.path.append(os.getcwd())
>>> from .._foo import baz
ValueError: attempted relative import beyond top-level package
>>> from ._foo import baz
ModuleNotFoundError: No module named 'package' 

I intend this to be released for public use, so tricks that only work for my machine are not really useful for me (referring to some sys.path or PYTHONPATH tricks I found).

Upvotes: 2

Views: 938

Answers (1)

wim
wim

Reputation: 363476

Running scripts from within a package is not supported in Python, because Guido considered that an antipattern.

Existing solutions are running bar as a module:

python -m package.subpackage.bar

Or creating a console_scripts entrypoint:

# in setup.py
from setuptools import setup

setup(
    ...
    entry_points={
        "console_scripts": [
            "mybarscript=package.subpackage.bar:myfunc",
        ]
    }
)

When package is installed, a Python script called mybarscript will be autogenerated. It will hook into the callable myfunc defined in bar.py.

Upvotes: 3

Related Questions