兄弟包导入 [英] Sibling package imports

查看:25
本文介绍了兄弟包导入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've tried reading through questions about sibling imports and even the package documentation, but I've yet to find an answer.

结构如下:

├── 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 模块并从命令行运行?

How can the scripts in the examples and tests directories import from the api module and be run from the commandline?

另外,我想避免对每个文件进行丑陋的 sys.path.insert hack.一定这可以在 Python 中完成,对吧?

Also, I'd like to avoid the ugly sys.path.insert hack for every file. Surely this can be done in Python, right?

推荐答案

七年后

自从我在下面写了答案后,修改 sys.path 仍然是一个快速而肮脏的技巧,适用于私有脚本,但已经有了一些改进

Seven years after

Since I wrote the answer below, modifying sys.path is still a quick-and-dirty trick that works well for private scripts, but there has been several improvements

    尽管我建议使用 pip这样做而不是直接使用 setuptools(并使用 setup.cfg 来存储元数据)
  • 使用 -m 标志并作为包运行也可以(但会转如果你想把你的工作目录转换成一个可安装的包,那就有点尴尬了).
  • 对于测试,具体来说,pytest 能够在这种情况下找到 api 包并处理 sys.path 为您提供的技巧
  • Installing the package (in a virtualenv or not) will give you what you want, though I would suggest using pip to do it rather than using setuptools directly (and using setup.cfg to store the metadata)
  • Using the -m flag and running as a package works too (but will turn out a bit awkward if you want to convert your working directory into an installable package).
  • For the tests, specifically, pytest is able to find the api package in this situation and takes care of the sys.path hacks for you

所以这真的取决于你想做什么.但是,在您的情况下,由于您的目标似乎是在某个时候制作适当的软件包,因此通过 pip -e 安装可能是您最好的选择,即使它还不完美.

So it really depends on what you want to do. In your case, though, since it seems that your goal is to make a proper package at some point, installing through pip -e is probably your best bet, even if it is not perfect yet.

正如在其他地方已经说过的,可怕的事实是,你必须做一些丑陋的 hack 才能允许从 __main__ 模块导入兄弟模块或父包.PEP 366 中详细介绍了该问题.PEP 3122 试图以更合理的方式处理导入,但 Guido 拒绝了它一个帐号

As already stated elsewhere, the awful truth is that you have to do ugly hacks to allow imports from siblings modules or parents package from a __main__ module. The issue is detailed in PEP 366. PEP 3122 attempted to handle imports in a more rational way but Guido has rejected it one the account of

唯一的用例似乎是运行发生的脚本生活在一个模块的目录中,我一直将其视为一个反模式.

The only use case seems to be running scripts that happen to be living inside a module's directory, which I've always seen as an antipattern.

(这里)

不过,我经常使用这种模式

Though, I use this pattern on a regular basis with

# 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]) 是您的顶级文件夹.

Here path[0] is your running script's parent folder and dir(path[0]) your top level folder.

尽管如此,我仍然无法使用相对导入,但它确实允许从顶层(在您的示例 api 的父文件夹中)进行绝对导入.

I have still not been able to use relative imports with this, though, but it does allow absolute imports from the top level (in your example api's parent folder).

这篇关于兄弟包导入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆