如何在轮子中包含和安装测试文件并部署到 Databricks

2024-01-16

我正在开发一些在 Databricks 上运行的代码。鉴于 Databricks 无法在本地运行,我需要在 Databricks 集群上运行单元测试。问题是当我安装包含我的文件的轮子时,测试文件永远不会安装。如何安装测试文件?

理想情况下我想保留src and tests在单独的文件夹中。


这是我的项目(pyproject.toml仅)文件夹结构:

project
├── src
|   ├── mylib
│       ├── functions.py
│       ├── __init__.py
├── pyproject.toml
├── poetry.lock
└── tests
    ├── conftest.py
    └── test_functions.py

My pyproject.toml:

[tool.poetry]
name = "mylib"
version = "0.1.0"
packages = [
    {include = "mylib", from = "src"},
    {include = "tests"}
]

[tool.poetry.dependencies]
python = "^3.8"
pytest = "^7.1.2"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Without {include = "tests"} in pyproject.toml, poetry build不包括测试。

After poetry build我可以看到测试包含在生产的车轮中(python3 -m wheel unpack <mywheel.whl>)。但是当我将其部署为 Databricks 集群上的库后,我没有看到任何测试文件夹(ls -r .../site-packages/mylib*在 Databricks 笔记本 shell 单元中)functions.py已安装。

我也尝试过移动tests under src并将 toml 更新为{include = "tests", from = "src"},但是生成的轮子文件包含mylib & tests具有适当的文件,但仅mylib安装在 Databricks 上。

project
├── src
|   ├── mylib
│   │   ├── functions.py
│   │   └── __init__.py
|   └── tests
│       ├── conftest.py
│       └── test_functions.py
├── pyproject.toml
└── poetry.lock

正如有人试图指出的那样dbx作为解决方案,我尝试使用它。这不起作用。它有一系列基本限制(例如必须使用 ML 运行时),这使得它毫无用处,更不用说它希望您使用它推荐的任何工具集。也许几年后它就能满足这篇文章的需要。


如果其他人正在受苦,这就是我们最终所做的。

TL;DR;

  • 创建一个unit-test-runner.py可以安装一个wheel文件并在其中执行测试。关键是将其安装在“笔记本范围”。
  • 部署/复制unit-test-runner.py到 databricks dbfs 并创建一个指向它的作业。 Job参数是轮文件pytest.
  • 创建代码的wheel,将其复制到databricks dbfs,使用wheel文件的位置作为参数运行作业unit-test-runner。

项目结构:

root
├── dist
│   └── my_project-0.1.0-py3-none-any.whl
├── poetry.lock
├── poetry.toml
├── pyproject.toml
├── module1.py
├── module2.py
├── housekeeping.py
├── common
│   └── aws.py
├── tests
│   ├── conftest.py
│   ├── test_module1.py
│   ├── test_module2.py
│   └── common
│       └── test_aws.py
└── unit_test_runner.py

unit-test-runner.py

import importlib.util
import logging
import os
import shutil
import sys
from enum import IntEnum

import pip
import pytest


def main(args: list) -> int:
    coverage_opts = []
    if '--cov' == args[0]:
        coverage_opts = ['--cov']
        wheels_to_test = args[1:]
    else:
        wheels_to_test = args

    logging.info(f'coverage_opts: {coverage_opts}, wheels_to_test: {wheels_to_test}')

    for wh_file in wheels_to_test:
        logging.info('pip install %s', wh_file)
        pip.main(['install', wh_file])
        # we assume wheel name like <pkg name>-version-...
        # E.g. my_module-0.1.0-py3-none-any.whl
        pkg_name = os.path.basename(wh_file).split('-')[0]
        # don't import module to avoid any issues with coverage data.
        pkg_root = os.path.dirname(importlib.util.find_spec(pkg_name).origin)
        os.chdir(pkg_root)

        pytest_opts = [f'--rootdir={pkg_root}']
        pytest_opts.extend(coverage_opts)

        logging.info(f'pytest_opts: {pytest_opts}')
        rc = pytest.main(pytest_opts)
        logging.info(f'pytest-status: {rc}/{os.waitstatus_to_exitcode(rc)}, wheel: {wh_file}')
        generate_coverage_data(pkg_name, pkg_root, wh_file)

        return rc.value if isinstance(rc, IntEnum) else rc


def generate_coverage_data(pkg_name, pkg_root, wh_file):
    if os.path.exists(f'{pkg_root}/.coverage'):
        shutil.rmtree(f'{pkg_root}/htmlcov', ignore_errors=True)
        output_tar = f'{os.path.dirname(wh_file)}/{pkg_name}-coverage.tar.gz'
        rc = os.system(f'coverage html --data-file={pkg_root}/.coverage && tar -cvzf {output_tar} htmlcov')
        logging.info('rc: %s, coverage data available at: %s', rc, output_tar)


if __name__ == "__main__":
    # silence annoying logging
    logging.getLogger("py4j").setLevel(logging.ERROR)
    logging.info('sys.argv[1:]: %s', sys.argv[1:])
    rc = main(sys.argv[1:])
    if rc != 0:
        raise Exception(f'Unit test execution failed. rc: {rc}, sys.argv[1:]: sys.argv[1:]')

  • 安装和配置databricks-cli. 请参阅此处的说明 https://docs.databricks.com/dev-tools/cli/index.html.
WORKSPACE_ROOT='/home/kash/workspaces'
USER_NAME='[email protected] /cdn-cgi/l/email-protection'
cd $WORKSPACE_ROOT/my_project
echo 'copying runner..' && \
  databricks fs cp --overwrite unit_test_runner.py dbfs:/user/$USER_NAME/
  • Go to databricks GUI and create a job https://docs.databricks.com/workflows/jobs/jobs.html#create-a-job pointing to dbfs:/user/$USER_NAME/unit_test_runner.py. Can also be done using CLI.
    • 工作类型:Python 脚本
    • 来源:DBFS/S3
    • Path: dbfs:/user/$USER_NAME/unit_test_runner.py
  • Run databricks jobs list查找工作 ID,例如123456789
cd $WORKSPACE_ROOT/my_project
poetry build -f wheel # could be replaced with any builder that creates a wheel file
whl_file=$(ls -1tr dist/my_project*-py3-none-any.whl | tail -1 | xargs basename)
echo 'copying wheel...' && databricks fs cp --overwrite dist/$whl_file dbfs:/user/$USER_NAME/wheels
echo 'running job.....' && echo "launching job.." && \
  databricks jobs run-now --job-id 123456789 --python-params "[\"/dbfs/user/$USER_NAME/wheels/$whl_file\"]"
# OR with coverage
echo 'running job..' && echo "launching job with coverage.." && \
  databricks jobs run-now --job-id 123456789 --python-params "[\"--cov\", \"/dbfs/user/$USER_NAME/wheels/$whl_file\"]"

如果你和--cov然后选择获取并打开覆盖率报告:

rm -f htmlcov/ my_project_coverage_report.tar.gz
databricks fs cp dbfs:/user/$USER_NAME/wheels/my_project_coverage_report.tar.gz .
tar -xvzf my_project_coverage_report.tar.gz
firefox htmlcov/index.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在轮子中包含和安装测试文件并部署到 Databricks 的相关文章

  • 如何在anaconda python 3.6上安装tensorflow

    我使用 anaconda 包安装了新版本的 python 3 6 但是我无法安装张量流 总是收到这样的错误 tensorflow gpu 1 0 0rc2 cp35 cp35m win amd64 whl 在此平台上不受支持 如何在 ana
  • 使用 Python 将列名称与 CSV 文件中的数据对齐

    这是我用来将数据写入 csv 文件的代码 with open temp csv a as fp a csv writer fp delimiter t data faceXpos faceYpos faceHeight faceWidth
  • 打开文件路径在 python 中不起作用[重复]

    这个问题在这里已经有答案了 我正在编写一个数据库程序 personica 是我的测试主题 我通常在文件路径的位置有一个变量 但出于测试和演示的目的 我只有一个字符串 在我的计算机上的这个确切位置有一个文本文件 顺便说一句 因为我很偏执 所以
  • 以编程方式结束/退出粘合作业

    我正在使用 Glue 书签来处理数据 我的工作是每天安排的 但也可以 手动 启动 由于我使用书签 有时胶水作业可以在没有新数据要处理的情况下启动 然后读取的数据帧为空 在这种情况下 我想好好地结束我的工作 因为它没有什么关系 我试过 if
  • NLTK:包错误?朋克和泡菜?

    基本上 我不知道为什么会收到此错误 只是为了获得更多图像 这里有一个代码格式的类似消息 由于是最新的 该帖子的答案已经在消息中提到 Preprocessing raw texts LookupError Traceback most rec
  • 如何使用格式保存 Tkinter 文本小部件的内容

    我在 python 中使用 Tkinter 在文本窗口中显示输出 我发现使用 get 功能我可以从此窗口检索文本内容 但我有用不同背景颜色标记的文本部分 是否可以将内容与这些颜色一起复制到文件 例如 html 或 doc 中 没有对你想要的
  • 在Python中整齐地绘制PMF

    有没有一个库可以帮助我在 python 中整齐地绘制样本的概率质量函数 如下所示 通过matplotlib pyplot的stem模块 matplotlib pyplot stem args kwargs from matplotlib p
  • PyQt5 的 OpenGL 模块和版本控制问题(调用不正确的 _QOpenGLFunctions_(ver))

    我一直在努力得到PyQt5 helloGL 示例代码 https github com baoboa pyqt5 blob master examples opengl hellogl py编译 当我尝试构建解决方案时 我得到 Traceb
  • 我可以在pycharm中的断点处进入交互模式吗

    我是一个相当新的 Pycharm 3 用户 正在从事 django 项目 我可以在 pycharm3 中的断点处进入交互模式吗 这可能吗 当程序在断点处停止时 我尝试过工具 gt 打开调试命令行 但我没有看到控制台打开 我怎样才能让它发挥作
  • django-allauth:电子邮件确认

    我已经设置了 django allauth 并在新用户注册时使用电子邮件确认 效果很好 但在确认电子邮件中 我得到 Hello from example com You re receiving this e mail because us
  • 如何检查discord.py中的所有者

    我试图让这个命令只有所有者才能运行它 是否有办法检查服务器的最高角色或创建者 我尝试了 commands is owner 但这仅检查某人是否是机器人的所有者 Guild owner https discordpy readthedocs
  • 如何在 Angular 单元测试中创建假 NgForm 对象?

    我有一个带有如下模板的组件 Template
  • Python:两个列表之间的成对比较:列表 a >= 列表 b?

    如果我想检查列表中的所有元素 a 1 2 3 6 大于或等于另一个列表中对应的元素 b 0 2 3 5 如果 a i gt b i 对于所有i的 则返回 true 否则返回 false 这有逻辑功能吗 比如a gt b 谢谢 你可以这样做
  • 如果任何单元测试失败,如何使 Python 的覆盖率工具失败?

    我想使用 shell 脚本来确保我的单元测试通过and我的代码有足够的测试覆盖率 我只想运行我的测试代码once 我希望我可以通过coverage https coverage readthedocs io 工具和单次运行的工具 如果一项或
  • 如何在 Python 中连接两个列表?

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 如何在 Python 中连接两个列表 Example listone 1 2 3 lis
  • Python-使用元组作为列表索引[重复]

    这个问题在这里已经有答案了 我有一个元组列表 tuples list 1 0 2 3 3 2 2 0 我想访问二维数组的元素a例如 使用其中一些元组 for i in range 3 print a tuples list i 应该输出的值
  • 检查图像中是否有太薄的区域

    我正在尝试验证雕刻机的黑白图像 更多的是剪贴画图像 不是照片 我需要考虑的主要事情之一是区域的大小 或线条的宽度 因为机器无法处理太细的线条 所以我需要找到比给定阈值更细的区域 以此图为例 竖琴的琴弦可能太细而无法雕刻 我正在阅读有关 Ma
  • 如何动态选择要在flask中使用的模板目录?

    默认情况下 Flask 使用存储在 template 目录中的模板文件 flaskapp application py templates hello html 有没有办法根据登录的用户动态选择模板目录 这就是我想要的目录结构 flaska
  • 内置模块位于哪里?

    我尝试查找列出的所有目录sys path但我找不到任何builtins py文件 那么它在哪里呢 从字面上看 该模块内置于 python 解释器中 gt gt gt import builtins gt gt gt builtins
  • 如何使用多阶段构建减小 python (docker) 图像大小?

    我正在寻找一种使用 python 和 Dockerfile 创建多阶段构建的方法 例如 使用以下图像 第一张图片 安装所有编译时要求 并安装所有需要的 python 模块 第二张图片 将所有已编译 构建的包从第一个映像复制到第二个映像 而不

随机推荐

  • Blade.php 方法将结果输出到表单

    我目前正在使用 Laravel 4 2 框架和 twitter bootstrap 设计一个网站 我已经设置了我的master blade php文件 在每个页面的顶部显示一个导航栏 基本上 如果用户登录 我想显示一个导航栏 其选项与用户未
  • 如何将一列中的数据分成两列?

    我最近刚刚开始学习 MS Access 和 SQL Server 中的 SQL 所以我的知识非常有限 但我正在寻找有关 MS Access 中查询的帮助 我知道如何将 2 列合并为 1 列 并用逗号或我想要的任何符号分隔最终结果 但是 我该
  • 错误:找不到您尝试购买的商品

    我是一名安卓初学者 我创建了一个测试应用程序 它只有一个按钮 当您单击它时 它会启动应用内购买 几天前还可以用 但现在不行了 我还检查了其他相关帖子 我尝试了所有 测试帐户 和 活动应用内产品 方法 但它仍然给我相同的错误消息 另外 我尝试
  • 有没有办法更改未使用 basicConfig 配置的记录器对象的文件模式?

    如果我使用 logger logging getLogger Name 创建记录器对象 我无法将文件模式从追加 a 更改为写入 w 如果我将根记录器与 basicConfig 一起使用 则可以 但是当我想要的只是从 DEBUG 级别开始的我
  • 根据匹配的行合并两个csv文件并在linux中添加新列

    我正在使用 java 开发一个应用程序 但为此我需要一个按顺序排列的 csv 文件 我对linux不太了解 但想知道是否有某种方法可以将csv文件合并为所需的格式 我有两个 csv 文件 其中包含数十万条记录 示例如下 name Direc
  • 如何列出Qt5的所有CMake组件?

    我知道在 CMake 中我可以找到并需要我需要的 Qt5 库 代码如下 find package Qt5 5 12 0 REQUIRED COMPONENTS Gui Qml QuickControls2 Svg 但我怎么知道我可以在后面列
  • 在 Fabric8 Kubernetes 客户端 events() API 的 Watcher 中,我可以监视哪些资源?

    我正在探索 无证 events API https github com fabric8io kubernetes client blob master kubernetes client src main java io fabric8
  • Qt 中区分单击事件和双击事件

    我有一个QAbstractItemView需要对单击和双击事件做出反应 根据单击还是双击 操作会有所不同 发生的问题是在双击事件之前接收到单击事件 是否有推荐的方法 最佳实践来区分两者 当用户实际双击时 我不想执行单击操作 我正在使用 Qt
  • 在内联表单集中使用 Django FileField

    在我的应用程序中上传文件时遇到问题 用户提交报告并可以添加附件 通过外键关系 我已经显示了内联表单 如果我将其留空 它就会工作 但是当我尝试上传文件然后提交表单时 我收到 500 错误 基本报告已制作 但内联的附件未保存 forms py
  • 如何调用Fragment的onResume()

    我使用了导航抽屉 其中有许多片段 我想调用fragment的onResume 我需要从服务器加载更新的数据 onResume 当你的Activity onResume 已被调用 您不必调用onResume in a Fragment 阅读本
  • Python 编码风格 - 多个返回语句[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 对于同一任务 我编写了两个不同的函数 我想知道哪一个使用起来更优雅 任务是检查一个pydot如果它看到请求的节点 则返回对象 如果是 则返回该节
  • 让 google Recaptcha 能够处理域名中的特殊字符

    我正在为域名中包含瑞典字符 的网站设置 API 密钥 http s lja io http s C3 A4lja io 但它没有初始化验证码 然后尝试使用等效 url 的 api 密钥http xn slja loa io http xn
  • android studio 模拟器无法初始化 DirectSoundCapture

    我在 android studio 3 2 中只有一个基本的 helloworld 应用程序 我正在尝试运行一些模拟器来使用 AVD 管理器测试该应用程序 但模拟器只是停留在 google 徽标中 最终 android studio 超时并
  • Android Studio 2 Beta 5 中的构建变体中测试工件选择器丢失/消失

    为了在 Android Studio 中运行 Instrumentation Tests 我通常通过 Build Variants 窗 口选择 Android Instrumentation Tests 作为要构建的测试工件 我最近升级到
  • 注入存储库上的 IDisposable

    我有以下 ADO Net 存储库 public class Repository IRepository IDisposable private readonly IUnitOfWork UnitOfWork private SqlConn
  • 使用 Ext.grid.Panel.reconfigure() 破坏网格 RowEditing 插件

    我正在创建一个 extjs 网格面板 其中有一组用户可配置的列 这Ext grid Panel http docs sencha com ext js 4 1 api Ext grid Panel组件提供了一个方便的reconfigure
  • 如何将卫星程序集(本地化资源)包含在使用 WiX 构建的 MSI 中?

    我正在从事的项目正在从使用 VS2008 部署 安装程序切换到 WiX 我目前对 WiX 还很陌生 我添加了将资源项目的输出复制到 Resources dll 中的代码 但在旧的 VS2008 安装程序文件系统中 还存在本地化资源输出 该输
  • 调用 mouseClicked() 后 JComponent 消失

    我正在用 Swing 编写一个 Java GUI 程序 界面如下所示 当用户单击右侧的其中一张图片时 我希望在左上角的橙色区域中显示它的小预览 我通过以下方式从计算机上的目录中提取所有图像文件SwingWorker线程 http docs
  • 无法打开登录请求的服务器

    我正在尝试使用 pyodbc 连接到我的 Azure SQL 数据库 我正在使用的azure帐户位于用户名下 电子邮件受保护 cdn cgi l email protection 我的大学帐户 当我尝试连接到数据库时 出现错误 Cannot
  • 如何在轮子中包含和安装测试文件并部署到 Databricks

    我正在开发一些在 Databricks 上运行的代码 鉴于 Databricks 无法在本地运行 我需要在 Databricks 集群上运行单元测试 问题是当我安装包含我的文件的轮子时 测试文件永远不会安装 如何安装测试文件 理想情况下我想