首页 > 解决方案 > 从父包导入模块

问题描述

我有一个如下结构:

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

我正在尝试_foo从内部导入bar

# bar.py
from .._foo import baz

def myfunc():
    baz()
    # stuff

bar.py作为脚本运行时(例如,在 Jupyter Notebook 中,甚至python bar.py使用python -m package.subpackage.bar. 我无法让它工作:

>>> 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' 

我打算将其发布以供公众使用,因此仅适用于我的机器的技巧对我来说并不真正有用(指的是我发现的一些sys.path技巧PYTHONPATH)。

标签: pythonpython-3.ximport

解决方案


Python 不支持从包中运行脚本,因为Guido 认为这是一种反模式

现有的解决方案是将 bar 作为一个模块运行:

python -m package.subpackage.bar

或创建一个console_scripts 入口点

# in setup.py
from setuptools import setup

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

package安装后,将自动生成一个名为的 Python脚本mybarscript。它将挂钩myfuncbar.py.


推荐阅读