CertSafari
    Databricks Certified Data Engineer Professional· Lessons

    Domain 1 · Lesson 1/46

    Python code in bundles: wheel artifacts, library dependencies, and Python-defined resources

    Implement scalable Python project structures for Declarative Automation Bundles (formerly Databricks Asset Bundles / DABs) to support modular development and CI/CD integration.

    11 min read
    1.92% of exam
    3 sources
    Published 3 Oct 2026
    Docs as of 30 Sep 2026

    What you will be able to do

    • Configure an artifacts mapping that builds a Python wheel with uv, Poetry or setuptools
    • Declare whl, PyPI and requirements.txt dependencies on bundle job tasks
    • Wire pyproject.toml dependencies into a pipeline with an editable environment
    • Define and generate bundle resources in Python with the python section and load_resources

    1.Building your src/ package as a wheel artifact

    In a scalable bundle, shared logic belongs in a Python package under src/ that is built into a wheel, not copied between notebooks. The default-python template already does this: it builds the wheel with uv from a pyproject.toml. The build is set in the top-level artifacts mapping in databricks.yml.

    An artifacts entry that builds a wheel with uvyaml
    # databricks.yml
    ...
    artifacts:
      python_artifact:
        type: whl
        build: uv build --wheel
    ...

    Checkpoint 1 of 6· Fill the gap

    What artifact type tells the bundle it is building a Python wheel?

    artifacts:
      python_artifact:
        type:  ? 
        build: uv build --wheel

    uv is not the only option. The documentation also shows Poetry (build: poetry build) and setuptools builds that keep the package under src/my_package with __init__.py, main.py and my_module.py. The task then runs the package through a python_wheel_task and lists the built file under libraries as ./dist/*.whl.

    Deploying the bundle builds the wheel. The built file goes into the bundle's workspace folder under .bundle/<project-name>/dev/artifacts/.internal/. If the wheel was already built somewhere else, such as an earlier CI step, you leave out the artifacts mapping.

    Checkpoint 2 of 6· Check yourself

    A CI pipeline builds the wheel in an earlier step. The team removes the artifacts mapping from databricks.yml but keeps - whl: ./dist/*.whl under the task's libraries. What does bundle deploy do?

    Sources1

    2.Declaring library dependencies on tasks

    Jobs and pipelines also depend on outside libraries, and these are declared in the bundle configuration too. Python dependencies on a job task go in its libraries list as wheel files, PyPI packages or a requirements file. JARs and Maven or CRAN packages are also supported.

    Three wheel sources on one task: local path, workspace files, Unity Catalog volumeyaml
    resources:
      jobs:
        my_job:
          # ...
          tasks:
            - task_key: my_task
              # ...
              libraries:
                - whl: ./my-wheel-0.1.0.whl
                - whl: /Workspace/Shared/Libraries/my-wheel-0.0.1-py3-none-any.whl
                - whl: /Volumes/main/default/my-volume/my-wheel-0.1.0.whl
    Python library mappings available under a task's libraries
    MappingFieldsNotes
    whlpath to the .whlFrom workspace files, Unity Catalog volumes, cloud object storage, or a local path
    pypipackage (optional exact version), optional repoWithout repo, the default pip index https://pypi.org/simple/ is used
    requirementspath to a requirements*.txtLocal, workspace, or Unity Catalog volume path
    jar / mavenpath / coordinates, repo, exclusionsFor Java or Scala dependencies

    Where the files are stored matters. Storing libraries in the DBFS root is deprecated and turned off by default from Databricks Runtime 15.1, because any workspace user can change files there. Databricks recommends workspace files, Unity Catalog volumes or package repositories instead.

    Checkpoint 3 of 6· Match them up

    Match each libraries entry to what it installs

    Tap a term, then the definition that fits it.

    Sources2

    3.pyproject.toml with uv, and the pipeline exception

    The recommended way to manage Python dependencies is uv, with dependencies listed in the bundle's pyproject.toml. The template's pyproject keeps runtime dependencies apart from a dev dependency group used for local work (pytest, ruff, databricks-dlt, databricks-connect, ipykernel). The deployed code then needs only the runtime set.

    To give a pipeline every dependency in pyproject.toml, add an editable environment to the pipeline resource that points to the folder where pyproject.toml is deployed. The example also shows two other structural habits: catalog and schema come from bundle variables, and the source is picked up with a glob over the transformations/ folder.

    A serverless pipeline installing the bundle's pyproject dependencies through an editable environmentyaml
    resources:
      pipelines:
        test_uv_etl:
          name: test_uv_etl
          catalog: ${var.catalog}
          schema: ${var.schema}
          serverless: true
          root_path: '../src/test_uv_etl'
    
          libraries:
            - glob:
                include: ../src/test_uv_etl/transformations/**
    
          environment:
            dependencies:
              - --editable ${workspace.file_path}

    Checkpoint 4 of 6· Exam question

    An engineer is configuring `dev` and `prod` targets in a single `databricks.yml` so the same bundle can be validated by individual developers and deployed unattended by a CI/CD pipeline into a shared production workspace. Which two configuration choices are appropriate for the `prod` target specifically? (Choose 2.)(Select 2)

    Sources2

    4.Defining resources in Python

    Resource definitions do not have to be YAML. With Python support for bundles you can define resources in Python code alongside YAML resources. You can also generate resources from metadata during deployment, and change YAML- or Python-defined resources while deploying. It needs Databricks CLI 0.275.0 or above. The databricks bundle init pydabs template sets it up.

    A job defined with dataclass syntax from the databricks-bundles packagepython
    from databricks.bundles.jobs import Job, Task, NotebookTask
    
    
    my_pydabs_project_job = Job(
        name="my_pydabs_project_job",
        tasks=[
            Task(
                task_key="notebook_task",
                notebook_task=NotebookTask(
                    notebook_path="src/notebook.ipynb",
                ),
            ),
        ],
    )

    Job.from_dict accepts the same structure as a Python dictionary. databricks.yml connects these files through a python section. That section names the virtual environment, which must contain the databricks-bundles package, and the function that loads the resources.

    The python section in databricks.ymlyaml
    python:
      # Activate the virtual environment before loading resources defined in
      # Python. If disabled, it defaults to using the Python interpreter
      # available in the current shell.
      venv_path: .venv
      # Functions called to load resources defined in Python.
      # See resources/__init__.py
      resources:
        - 'resources:load_resources'

    By default, load_resources in resources/__init__.py loads every Python file in the resources package. The CLI calls it during deployment, and it is not used after that. Because it is ordinary Python, it can build resources in a loop. This is a scalable pattern when many jobs differ only by a parameter.

    Generating one job per country inside load_resourcespython
    def load_resources(bundle: Bundle) -> Resources:
        resources = load_resources_from_current_package_module()
    
    
        for country in ["US", "NL"]:
            resources.add_resource(f"my_job_{country}", create_job(country))
    
    
        return resources

    Checkpoint 5 of 6· Check yourself

    A team with an existing YAML bundle wants to generate 40 near-identical jobs in Python. Which statement is correct?

    Checkpoint 6 of 6· Exam question

    A CI/CD pipeline runs `databricks bundle deploy --target prod` against the `prod` target, which has `mode: production` set. The deploy fails with an error stating that a `run_as` identity must be specified for the target. What is the most direct fix that keeps the production deployment unattended and reproducible?

    Sources3

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 1.If a bundle has no artifacts mapping, no wheel is deployed for its python_wheel_task.Why is that wrong?

      Without artifacts, the CLI treats the wheel as already built and deploys the whl files listed under libraries. Leaving out the mapping is the documented way to deploy a wheel built elsewhere.

      Covered in Building your src/ package as a wheel artifact

    2. 2.Adding a package to pyproject.toml is enough for a bundle-deployed pipeline to use it during development.Why is that wrong?

      Pipeline dependencies are cached during development. Declare them in the pipeline's environment section, for example as an editable install of the deployed project.

      Covered in pyproject.toml with uv, and the pipeline exception

    3. 3.Uploading wheels to the DBFS root is still the standard place for bundle libraries.Why is that wrong?

      Libraries in the DBFS root are deprecated and turned off by default on newer runtimes. Use workspace files, Unity Catalog volumes or package repositories.

      Covered in Declaring library dependencies on tasks

    Practise it for real

    Create a default-python bundle that builds a wheel from src/, deploy it to the dev target, and run its job

    1. 1.Run databricks bundle init, keep the default-python template, answer no to the notebook job and ETL pipeline, yes to the sample Python package and serverless, and enter an existing Unity Catalog catalog

      Why: The template produces the standard layout: databricks.yml, resources/sample_job.job.yml, src/ and tests/

      You should see: A new project folder (my_project by default) with those files

    2. 2.From the bundle root, run databricks bundle validate

      Why: Validation catches configuration errors before anything reaches the workspace

      You should see: A summary of the bundle configuration and no errors

    3. 3.Run databricks bundle deploy --target dev

      Why: Deploying builds the wheel from src/ and creates the job in development mode

      You should see: The .whl under .bundle/<project-name>/dev/artifacts/.internal and a job named [dev <your-username>] sample_job with one python_wheel_task

    4. 4.Run databricks bundle run --target dev sample_job and open the printed Run URL

      Why: This confirms the deployed wheel's entry point runs as a job task

      You should see: The task finishes with a green title bar

    Stuck? Get a nudge

    If you change anything after deploying, validate and deploy again before the next run.

    Sources

    Every claim above is drawn from one of these pages, quoted as it was written on the date shown.

    1. 1.
      “a bundle is created that shows how to configure a bundle that builds a Python wheel using uv and pyproject.toml.”
      ↩︎ Building your src/ package as a wheel artifact
      “Next, deploy the bundle to your remote Databricks workspace. This builds the Python wheel file.”
      ↩︎ Building your src/ package as a wheel artifact
      “modify the following bundle configuration file by omitting the artifacts mapping.”
      ↩︎ Exam trap 1
      “The Databricks CLI will then assume that the Python wheel file is already built”
      ↩︎ Checkpoint
    2. 2.
      “Library dependencies are declared in your bundle configuration files.”
      ↩︎ Declaring library dependencies on tasks
      “Databricks recommends uploading all libraries, including Python libraries, JAR files, and Spark connectors, to workspace files or Unity Catalog volumes”
      ↩︎ Declaring library dependencies on tasks
      “uv is the recommended method for managing Python library dependencies.”
      ↩︎ pyproject.toml with uv, and the pipeline exception
      “adding an editable environment that points to the folder where pyproject.toml is deployed”
      ↩︎ pyproject.toml with uv, and the pipeline exception
      “add dependencies to the 'environment' section of your pipeline.yml file instead”
      ↩︎ Exam trap 2
      “storing library files in the DBFS root is deprecated and disabled by default in Databricks Runtime 15.1 and above.”
      ↩︎ Exam trap 3
      “Python library dependencies can also be specified in a requirements*.txt file that is included as part of the job task definition.”
      ↩︎ Checkpoint
      “LIMITATION: for pipelines, dependencies are cached during development;”
      ↩︎ Prediction
    3. 3.
      “Python files are loaded through an entry point specified in the python section in databricks.yml:”
      ↩︎ Defining resources in Python
      “After deployment, this function is not used.”
      ↩︎ Defining resources in Python
      “The specified virtual environment must contain the installed databricks-bundles PyPi package.”
      ↩︎ Defining resources in Python
      “You can use Python to create resources programmatically.”
      ↩︎ Defining resources in Python
      “These definitions can coexist with resources defined in YAML.”
      ↩︎ Checkpoint

    Ready to test yourself?

    Practise Databricks Certified Data Engineer Professional in quiz mode.

    Spotted a mistake, or was something unclear? Tell us.