兄弟包进口 [英] Sibling package imports

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

问题描述

我尝试阅读有关同级进口甚至进口商品的问题. 包装文档,但是我还没有找到答案.

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

  • 安装软件包(无论是否在virtualenv中)都可以为您提供所需的信息,尽管我建议您使用pip这样做,而不是直接使用setuptools(并使用setup.cfg存储元数据)
  • 使用-m标志并作为程序包运行也是可行的(但如果您这样做,会有些尴尬想要将您的工作目录转换为可安装的软件包.
  • 对于测试,具体来说, pytest 能够在这种情况下找到api包并负责为您骇客
  • 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.

正如在其他地方已经提到的那样,可怕的事实是,您必须进行丑陋的黑客攻击,以允许从同级模块或父级包从__main__模块导入. PEP 366 中对此问题进行了详细说明. PEP 3122 试图以更合理的方式处理进口,但圭多拒绝了一个帐户

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天全站免登陆