首页 > 编程问答 >有没有更好的方法来在存储库中的一组 python 程序之间共享公共代码

有没有更好的方法来在存储库中的一组 python 程序之间共享公共代码

时间:2024-07-25 07:47:57浏览次数:15  
标签:python python-import

当我想要快速、轻松地做许多不同的事情时,我会选择Python - 即我总是会得到许多Python“程序” - 例如一组脚本 - 或者如果我正在玩一些东西,一堆测试程序等 - 即始终是许多不同程序的松散集合。

但是,我会分享某些内容。 例如,如果我正在使用 AI - 我可能有 30 个左右完全不相关的程序 - 但它们都会调用 LLM。

目录结构

所以我在 Git 中总是想要的目录结构就像:

.
└── src/
    ├── common
    ├── program1
    ├── program2
    └── program3

不需要:显式设置

但我还没有找到任何好方法使program1、program2、program3引用以任何ide或linter都能理解的方式通用,直接从git中出来。 我知道我可以做一些事情,比如设置 python 路径等 - 但我希望有人能够克隆库 - 更改为 program1 并运行 python program1.py 它就可以工作 - 所以任何需要运行/设置/配置的东西都是只是不是我的选择。

想要:相对导入

我真正想要的是每个程序只做:

     from ..common import some_helper

但是当我尝试时,我当然得到

Error: attempted relative import with no known parent package

现在...如果我这样做:

import sys
import os
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, parent_dir)

大多数事情实际上都有效,但这就像我必须添加到每个 python 程序中的 4 行晦涩难懂的行 - 并且一些编辑器或 linter 找不到它。

这些程序实际上彼此无关,除了属于同一个存储库的一部分之外,因此任何共享的出身都是非常错误的。 它们通常还有一堆其他文件、数据文件、自述文件等 - 所以将所有内容都放在公共目录之上的同一目录中太混乱了。

我尝试过的替代方案:符号链接

我找到的唯一真正实用的解决方案到目前为止,只是将公共目录符号链接到所有其他目录中 - 它很丑陋 - 但它确实有效。

问题

是否有更好的方法 - 一种更Pythonic的方法?

我想从根本上来说 - 我想要知道如何在没有已知父包的情况下进行相对导入?


所面临的问题是,Python 在没有额外上下文的情况下无法将的项目目录结构识别为包。是对的,直接修改 sys.path 通常不是最干净的解决方案。

以下是一些更 Pythonic 的管理项目中共享代码的方法:

1. 使用 __init__.py 文件创建包:

  • 在的 src 目录以及 common program1 program2 等目录中创建空的 __init__.py 文件。这会将这些目录转变为 Python 包。
  • 现在,可以使用相对导入:

    python # 在 program1/program1.py 中 from ..common import some_helper

  • 优点: 这是 Pythonic 的方法,应该可以与大多数 IDE 和 linter 配合良好。

  • 缺点: 它要求在每个子目录中都有 __init__.py 文件,这在某些情况下可能看起来很笨拙。

2. 使用安装包:

  • 将的项目构建为一个适当的 Python 包(使用 setup.py pyproject.toml )。
  • 在的项目根目录中,运行 pip install -e . (“可编辑安装”)。这会将的包放在 Python 路径上,同时仍然允许对其进行编辑。
  • 现在,可以使用绝对导入:

    python # 在 program1/program1.py 中 from my_package.common import some_helper

  • 优点: 这是用于共享代码的最强大和最灵活的解决方案,尤其是在计划分发代码时。

  • 缺点: 它需要更多的初始设置,并且可能对这个特定用例来说有点过分。

3. 使用命名空间包(对于 Python 3.3+):

  • 命名空间包是仅包含其他包的包,它们不需要 __init__.py 文件。
  • 可以将 src 变成一个命名空间包,并以这种方式组织的代码。

  • 优点: 避免使用 __init__.py 文件,更清晰地分离关注点。

  • 缺点: 可能不如其他方法直接,需要了解命名空间包的工作原理。

关于的“没有已知父包”错误:

当运行 program1.py 时,Python 不会自动将 src 的父目录视为包层次结构的一部分。通过将的目录结构变成一个或多个包,将为 Python 提供必要的上下文来理解的相对导入。

符号链接方法:

虽然符号链接可以工作,但它不是一个非常便携或 Pythonic 的解决方案。它可能导致 IDE 和 linter 出现问题,并且在不同的操作系统上可能无法按预期工作。

建议:

对于的用例,我建议使用第一个或第二个选项。如果只需要一个简单的解决方案来使的代码正常工作,那么使用 __init__.py 文件创建包是最直接的方法。如果计划更广泛地分发的代码或需要更强大的解决方案,那么将其构建为一个适当的包是一个更好的选择。

标签:python,python-import
From: 78788006

相关文章

  • 如何在Python中从两个不同长度的列表创建DataFrame,为第二个列表中的每个值重复第一个
    我是一个超级初学者,所以请耐心等待。我觉得这应该很容易,但我无法弄清楚。我不确定是否应该创建两个列表,然后将它们组合起来,或者是否有办法以这种方式直接创建DataFrame。我需要一列包含这些值:df=pd.DataFrame({'x1':np.linspace(-2.47,2.69,num=101)})然后我将值A......
  • Python multiprocessing.connection.Connection 的行为不符合规范
    根据python规范,recv()pythonConnection的方法,(从multiprocessing.Pipe()返回,当管道为空且管道的另一端关闭时抛出EOFError(这里参考:https://docs.python.org/3.9/library/multiprocessing.html#multiprocessing.connection.Connection.re......
  • 使用 python Flask 发送邮件中的图像
    我想发送一封包含html代码和图像的电子邮件但在gmail中它说图像已附加,我不想要这样,我只想要电子邮件正文中的图像。html_content=f"<imgsrc="cid:banner"alt=""style="width:80%;">"msg=MIMEMultipart('related')html_part=MIMEText(html_c......
  • 在 python requests modul 中,如何检查页面是否使用“POST”方法或“GET”方法
    如何使用python“requests”模块检查页面是否使用“GET”方法或“POST”方法。我期望输出为True或False,或者GET或Post预期代码:importrequestsurl=f"www.get_example.com"response=requests.get(url)ifresponse.check_get==True:print("get")你......
  • VS Code Python - 如果括号(括号、大括号等)未关闭,内联建议不起作用
    我遇到的问题是,当我在未闭合的括号或方括号“内部”开始变量名称时,VSCode将不会显示任何建议。但是,如果在键入变量名称之前闭合括号,则建议效果很好。如果我可以避免它,我宁愿不将自动完成括号关闭设置为True也不使用TabOut扩展。第一个屏幕截图显示建议在闭括号/方......
  • 在 Azure 上部署代码时使用 Python 的多处理模块是否有意义?
    我们的团队在Azure机器学习(AML)上部署了一个Python脚本来处理存储在Azure存储帐户上的文件。我们的管道由一个ForEach活动组成,该活动调用每个或列出的文件的Python脚本。从Azure数据工厂(ADF)运行它会触发多个单独的管道同时运行......
  • 我已成功安装 pypdf2 但无法将其导入到我的 python 文件中
    我已经成功安装了pypdf2模块,但在导入它时,我发现该模块丢失了。我尝试使用fromPyPDF2importPdfReader导入,但它不起作用此问题的各种解决方案是什么?在尝试导入PyPDF2时遇到问题。以下是可能导致此问题的一些常见原因和解决方案:安......
  • Python3打开图片时请求ConnectionResetError(10054)
    我试图从'http://xxx.jpg'之类的网站下载图片。代码:headers={'user-agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/66.0.3359.139Safari/537.36'}url='http://xxx.jpg'resp......
  • Jupyter Notebook 环境中的 Python 版本不匹配
    我遇到Jupyter笔记本启动横幅中报告的Python版本与我在笔记本中查询python--version时显示的版本之间的差异。启动横幅指示Python3.11.9,但是当我运行!python--version时,它返回Python3.11.7。我所做的步骤:basecondahas3.11.7versio......
  • Python XML 解析:字符串中的“<”被阻塞
    我有一个使用ET.XMLParser来解析CppCheckXML报告文件的Python模块。当尝试解析字符串中包含“<”的XML元素中的属性之一时,它会令人窒息,它会将其解释为格式错误的XML,例如:<errormsg="Includefile<iostream>notfound.">(注意字符和“iostream”之间的空格必须放......