小编典典

Sibling package imports

python

我尝试阅读有关同级导入甚至 包文档的问题,但是我还没有找到答案。

具有以下结构:

├── LICENSE.md
├── README.md
├── api
│   ├── __init__.py
│   ├── api.py
│   └── api_key.py
├── examples
│   ├── __init__.py
│   ├── example_one.py
│   └── example_two.py
└── tests
│   ├── __init__.py
│   └── test_one.py

examplestests目录中的脚本如何 从api模块导入 并从命令行运行?

另外,我想避免sys.path.insert每个文件的难看。当然可以在Python中完成,对吗?


阅读 313

收藏
2021-01-20

共1个答案

小编典典

自从我在下面写下答案以来,修改sys.path仍然是一种快速技巧,适用于私有脚本,但是有一些改进

安装该软件包(无论是否在virtualenv中)都将为您提供所需的内容,尽管我建议使用pip进行操作,而不要直接使用setuptools(并setup.cfg用于存储元数据)
使用该-m标志并作为软件包运行也可以(但是如果要将工作目录转换为可安装的软件包,将会有些尴尬)。
对于测试,特别是pytest能够在这种情况下找到api程序包,并sys.path为您解决问题
因此,这实际上取决于您要做什么。但是,就您而言,既然您的目标似乎是在某个时候制作一个合适的程序包,那么通过安装pip -e可能是您的最佳选择,即使尚不完美。

旧答案
正如其他地方已经说过的那样,可怕的事实是,您必须进行丑陋的修改才能允许从同级模块中导入数据或从该__main__模块中的父级程序包中进行导入。PEP 366中详细介绍了该问题。PEP 3122试图以一种更合理的方式处理进口货,但圭多拒绝了它的原因

唯一的用例似乎是正在运行的脚本,它们恰好位于模块目录中,我一直将其视为反模式。

(这里)

不过,我会定期使用这种模式

# Ugly hack to allow absolute import from the root folder
# whatever its name is. Please forgive the heresy.
if __name__ == "__main__" and __package__ is None:
    from sys import path
    from os.path import dirname as dir

    path.append(dir(path[0]))
    __package__ = "examples"

import api

这path[0]是您正在运行的脚本的父文件夹和dir(path[0])顶级文件夹。

虽然我仍然不能使用相对导入,但是它确实允许从顶层(在您的示例api的父文件夹中)进行绝对导入。

2021-01-20