Declare dependencies
A managed workflow runs in a Python environment that it prepares in advance. The job cannot reach the internet, so it cannot pip install packages. Instead, Qiskit and a list of supported packages are already installed, and you can upload wheels for any other package that your workflow needs.
Check which packages are installed
Every job runs with Python 3.12 on Linux (x86_64), with the following packages installed:
qiskit,qiskit-ibm-runtime,qiskit-serverless, and their dependencies, such asnumpy.- The supported packages, such as
qiskit-aer,qiskit-addon-sqd,qiskit-addon-utils,qiskit-mitigation,qiskit-addon-slc,qiskit-paulice,ffsim, andpyscf. Each is installed at one fixed version.
To see the supported packages and their versions, call dependencies_versions() from your local notebook:
from qiskit_ibm_catalog import ManagedWorkflowClient
client = ManagedWorkflowClient()
client.dependencies_versions()Your workflow can import any of these packages without setup. The workflow installs them when it builds the environment, not when a job starts, so they do not add to the start time of a job.
A workflow does not read a requirements.txt or pyproject.toml file, so it does not install the packages that these files list. The dependencies argument of ManagedWorkflow is deprecated and ignored, so it does not install packages either. Remove it from your upload code, and upload wheels instead.
Packages on GPU compute profiles
Jobs that run on a GPU compute profile also have the following CUDA packages installed. These packages work only on a GPU profile, and dependencies_versions() does not list them. Do not upload your own CUDA wheels, because they conflict with these versions.
Package | Version |
|---|---|
gpu4pyscf-cuda12x | 1.8.1 |
gpu4pyscf-libxc-cuda12x | 0.8.1 |
cupy-cuda12x | 14.2.0 |
cutensor-cu12 | 2.8.0 |
cuda-pathfinder | 1.8.5 |
nvidia-cublas-cu12 | 12.9.3.13 |
nvidia-cuda-nvrtc-cu12 | 12.9.86 |
nvidia-cuda-runtime-cu12 | 12.9.79 |
nvidia-cufft-cu12 | 11.4.1.4 |
nvidia-curand-cu12 | 10.3.10.19 |
nvidia-cusolver-cu12 | 11.7.5.82 |
nvidia-cusparse-cu12 | 12.5.10.65 |
nvidia-nvjitlink-cu12 | 12.9.86 |
The nvidia-*-cu12 versions can change when the environment is rebuilt. Code that depends on an exact CUDA library version might need updates after a new release.
Request a package
If other users would also need a package, request it on GitHub. An accepted package is added to the environment in a later release. Until then, or for a private package, add it as a wheel.
Add your own packages
To use a package that is not installed, collect its wheel files on your computer, upload them to the workflow's file storage, and install them at the start of the workflow. You upload them again only when they change.
Build wheels
The job installs wheels without an internet connection, so each wheel must work with Python 3.12 on Linux (x86_64). Collect the wheels in one folder:
# Your own package
pip wheel --no-deps --wheel-dir wheels ./mypkg
# A package from PyPI, for the job's platform
pip download --only-binary=:all: --platform manylinux_2_28_x86_64 \
--python-version 3.12 --dest wheels pendulum==3.1.0With --platform and --python-version, pip download gets wheels for the job's platform, even when you run it on macOS or Windows. It also downloads the package's dependencies, such as python-dateutil, six, and tzdata for pendulum. Because the job installs each wheel without its dependencies, upload a wheel for every dependency that the environment lacks, and delete the other wheels from the folder.
A pure-Python wheel (py3-none-any.whl) works on any platform. If a package with compiled code has no Linux x86_64 wheel on PyPI, build one on Linux, for example in a python:3.12 container. Keep the original file names, because pip reads the package name, version, and platform from them.
Upload wheels
Upload the wheels from your local notebook with add_wheels():
from qiskit_ibm_catalog import ManagedWorkflowClient
client = ManagedWorkflowClient()
my_workflow = client.load("my-workflow")
client.add_wheels(my_workflow, ["wheels/*.whl"])
print(client.list_wheels(my_workflow))Each path can be a file name or a glob pattern, and add_wheels() returns the names of the uploaded wheels. If a pattern matches no files, or matches a file that is not a .whl file, add_wheels() raises a QiskitServerlessException.
Upload the workflow before you add wheels, because the wheels are stored with it. They go to a wheels folder in the workflow's file storage, separate from your other files.
Replace or remove wheels
To see the wheels that are uploaded to a workflow, call list_wheels(). To remove wheels, pass their file names to remove_wheels():
client.list_wheels(my_workflow)
# ['mypkg-1.0-py3-none-any.whl']
client.remove_wheels(my_workflow, ["mypkg-1.0-py3-none-any.whl"])To upgrade a package, remove the old wheel, and then add the new one. A new version has a different file name, so if you keep the old wheel, install_uploaded_wheels() installs both versions.
client.remove_wheels(my_workflow, ["mypkg-1.0-py3-none-any.whl"])
client.add_wheels(my_workflow, ["wheels/mypkg-1.1-*.whl"])Install wheels in your workflow
Edit your workflow code to call install_uploaded_wheels() before it imports the packages:
from qiskit_serverless import install_uploaded_wheels
install_uploaded_wheels()
import pendulum # Installed from an uploaded wheelinstall_uploaded_wheels() installs every wheel in the wheels folder. If the workflow has no wheels, the call does nothing. The wheels are installed again in every run, so a large set of wheels adds to the start time of each job.
Best practice: bring only missing packages
As a best practice, upload wheels only for the packages that the environment lacks. A wheel for an installed package, such as numpy, installs a second copy, and the code that imports it can get either copy. Errors from a mismatch appear only when the job runs.
Before you upload, check your requirements with dependency_report() from your local notebook:
print(client.dependency_report(["pendulum==3.1.0", "qiskit-aer", "qiskit-addon-sqd==0.10.0"]))requirement status note
pendulum==3.1.0 bring not in image — upload a wheel
qiskit-aer baked already in image (qiskit-aer==0.17.2)
qiskit-addon-sqd==0.10.0 clash image ships qiskit-addon-sqd==0.13.1The report gives each requirement one of the following statuses:
baked: The environment already provides the package. Do not upload a wheel for it.bring: The environment lacks the package. Upload a wheel for it.clash: The environment provides a different version. Change the version that your code requires, or rebuild your package for the installed version.
The report checks only the supported packages, so it shows qiskit, qiskit-ibm-runtime, qiskit-serverless, and numpy as bring. The environment includes them, so do not upload wheels for them. The report shows clash only for an exact == version. It shows a range, such as >=0.10, as baked. The report does not upload any files.
Troubleshoot dependencies
Problem | Cause |
|---|---|
pip install fails inside the workflow. | The job cannot reach the internet. Upload a wheel instead. |
ModuleNotFoundError for a package that you uploaded. | The workflow imports the package before it calls install_uploaded_wheels(). |
ModuleNotFoundError for a dependency of a package that you uploaded. | Wheels are installed without their dependencies. Upload a wheel for the missing dependency. |
The error says that a wheel is not a supported wheel on this platform. | The wheel is for another operating system or Python version. Get a wheel for Python 3.12 on Linux x86_64. |
install_uploaded_wheels() fails with ResolutionImpossible. | The wheels folder has two versions of the same package. Remove the old wheel with remove_wheels(). |
A CUDA package, such as cupy, fails on a GPU compute profile after you upload wheels. | A wheel replaced one of the CUDA packages that the environment provides. Remove that wheel with remove_wheels(). |
An installed package, such as numpy, fails after you upload wheels. | A wheel installed a second copy of a package that the environment provides. Remove that wheel with remove_wheels(). |