{"id":661,"library":"nbclient","title":"nbclient","description":"nbclient is a client library for programmatically executing Jupyter notebooks. It was originally spun out of `nbconvert`'s `ExecutePreprocessor` to allow for independent development and easier integration into other tools. It currently supports Python 3.10+ and releases minor versions frequently, typically every few weeks to months.","status":"active","version":"0.10.4","language":"python","source_language":"en","source_url":"https://github.com/jupyter/nbclient","tags":["jupyter","notebook","execution","automation","nbconvert"],"install":[{"cmd":"pip install nbclient","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Required for reading and writing Jupyter notebook files.","package":"nbformat","optional":false},{"reason":"Used internally by nbclient for managing Jupyter kernels.","package":"jupyter_client","optional":false}],"imports":[{"note":"The primary class for executing notebooks programmatically.","symbol":"NotebookClient","correct":"from nbclient import NotebookClient"},{"note":"Used to load and save notebook objects.","symbol":"nbformat","correct":"import nbformat"},{"note":"The `executenb` function was deprecated and moved from `nbconvert.preprocessors.execute` to `nbclient.execute`. Direct import from `nbclient` is recommended.","wrong":"from nbconvert.preprocessors.execute import executenb","symbol":"execute","correct":"from nbclient import execute"}],"quickstart":{"code":"import nbformat\nimport os\nfrom nbclient import NotebookClient\n\n# Create a dummy notebook for execution\nnotebook_content = {\n    \"cells\": [\n        {\n            \"cell_type\": \"code\",\n            \"source\": \"a = 1\\nb = 2\\nprint(a + b)\",\n            \"outputs\": [],\n            \"execution_count\": None\n        },\n        {\n            \"cell_type\": \"code\",\n            \"source\": \"import time\\ntime.sleep(0.1)\\nprint('Done sleeping')\",\n            \"outputs\": [],\n            \"execution_count\": None\n        }\n    ],\n    \"metadata\": {\n        \"kernelspec\": {\n            \"display_name\": \"Python 3\",\n            \"language\": \"python\",\n            \"name\": \"python3\"\n        },\n        \"language_info\": {\n            \"codemirror_mode\": {\n                \"name\": \"ipython\",\n                \"version\": 3\n            },\n            \"file_extension\": \".py\",\n            \"mimetype\": \"text/x-python\",\n            \"name\": \"python\",\n            \"nbconvert_exporter\": \"python\",\n            \"pygments_lexer\": \"ipython3\",\n            \"version\": \"3.10.0\"\n        }\n    },\n    \"nbformat\": 4,\n    \"nbformat_minor\": 5\n}\n\ninput_notebook_path = \"my_input_notebook.ipynb\"\noutput_notebook_path = \"my_executed_notebook.ipynb\"\n\nwith open(input_notebook_path, 'w', encoding='utf-8') as f:\n    nbformat.write(nbformat.from_dict(notebook_content), f)\n\n# Load the notebook\nwith open(input_notebook_path) as f:\n    nb = nbformat.read(f, as_version=4)\n\n# Configure and execute the notebook\n# Adjust timeout for potentially long-running cells or set to None/-1\nclient = NotebookClient(nb, timeout=600, kernel_name='python3')\ntry:\n    client.execute()\n    print(f\"Notebook '{input_notebook_path}' executed successfully.\")\nexcept Exception as e:\n    print(f\"Error executing notebook: {e}\")\n\n# Save the executed notebook with outputs\nwith open(output_notebook_path, 'w', encoding='utf-8') as f:\n    nbformat.write(nb, f)\n\nprint(f\"Executed notebook saved to '{output_notebook_path}'.\")\n\n# Clean up dummy notebook files\nos.remove(input_notebook_path)\nos.remove(output_notebook_path)","lang":"python","description":"This example demonstrates how to create a basic Jupyter notebook programmatically, execute it using `nbclient`, and then save the resulting notebook with its outputs. It also includes cleanup of the temporary files."},"warnings":[{"fix":"Upgrade your Python environment to 3.10 or newer, or pin `nbclient` to a compatible older version (e.g., `<0.10.2` for Python 3.9, `<0.10.0` for Python 3.8).","message":"nbclient has incrementally dropped support for older Python versions. Version 0.10.2 dropped Python 3.8 support, and 0.10.3 dropped Python 3.9 support. Users on these Python versions must upgrade their Python environment to 3.10+ or use an older `nbclient` version.","severity":"breaking","affected_versions":">=0.10.2"},{"fix":"Migrate imports from `from nbconvert.preprocessors.execute import ...` to `from nbclient import ...`. For example, `from nbconvert.preprocessors.execute import executenb` should become `from nbclient import execute`.","message":"nbclient was extracted from `nbconvert`'s `ExecutePreprocessor`. Code that previously imported `ExecutePreprocessor` or `executenb` from `nbconvert` needs to be updated to use `nbclient` directly.","severity":"breaking","affected_versions":"All versions (since nbclient's inception)"},{"fix":"When initializing `NotebookClient`, explicitly set `timeout` to a higher value (e.g., `timeout=600` for 10 minutes) or set it to `None` or `-1` to disable the timeout entirely.","message":"The `timeout` parameter in `NotebookClient` defaults to 30 seconds per cell. For notebooks with long-running cells, this can lead to `TimeoutError`. ","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure that the notebook content (dictionary) provided to `nbformat.from_dict` or similar constructors is valid and adheres to the `nbformat` specification. Specifically, verify that every cell object includes a `metadata` attribute, which should be a dictionary (even if empty). Consider using `nbformat.normalize()` on the notebook object before writing to resolve common structural issues if your `nbformat` version supports it.","message":"An `AttributeError: metadata` occurs during `nbformat.write`, specifically when `nbformat` attempts to process `cell.metadata` (e.g., in `strip_transient`). This indicates that a notebook cell object within the provided content is malformed and lacks the expected 'metadata' attribute. This often happens when the input dictionary passed to `nbformat.from_dict` does not strictly conform to the `nbformat` specification, where every cell (code, markdown, raw) must have a `metadata` dictionary.","severity":"breaking","affected_versions":"All versions where `nbformat` expects well-formed cell objects (observed on Python 3.9)"},{"fix":"Ensure that all cell objects within the notebook structure (e.g., passed to `nbformat.from_dict`) explicitly include a `metadata` attribute, even if it's an empty dictionary (e.g., `{'cell_type': 'code', 'source': '...', 'metadata': {}}`). Verify that the notebook content conforms to the `nbformat` schema before writing.","message":"An `AttributeError: metadata` occurs when `nbformat` attempts to write a notebook where one or more cell objects are missing the required `metadata` attribute. This typically happens when notebook content is programmatically constructed and does not fully adhere to the `nbformat` schema, which dictates that every cell must include a `metadata` dictionary.","severity":"breaking","affected_versions":"All nbformat versions that process notebook content according to the v4 schema (i.e., >=4.0)."}],"env_vars":null,"last_verified":"2026-05-12T17:32:15.071Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"Ensure 'nbformat' and 'nbclient' are installed in the active Python environment by running `pip install nbformat nbclient` or `conda install nbformat nbclient`.","cause":"The 'nbformat' package (a dependency of nbclient) is not installed in the Python environment being used, or there's a mismatch between the installed environment and where nbclient is trying to run.","error":"ModuleNotFoundError: No module named 'nbformat'"},{"fix":"Inspect the notebook's saved output or the detailed traceback provided by the error message to debug the specific code in the failing cell. To allow the notebook to continue executing even after an error, initialize `NotebookClient` with `allow_errors=True`.","cause":"A cell within the executed Jupyter notebook encountered an unhandled exception during its execution. By default, nbclient stops notebook execution and raises this error.","error":"nbclient.exceptions.CellExecutionError: An error occurred while executing the following cell:"},{"fix":"Increase the `timeout` parameter when initializing `NotebookClient` (e.g., `NotebookClient(nb, timeout=600)` for 10 minutes), or set `timeout=None` or `timeout=-1` to disable the timeout for all cells.","cause":"A specific cell in the notebook exceeded the maximum allowed execution time, which defaults to 30 seconds.","error":"nbclient.exceptions.CellTimeoutError: A cell timed out while it was being executed, after X seconds."},{"fix":"Check for sufficient system resources (RAM, CPU) if running locally, or increase allocated compute resources if on a cloud platform like Kaggle. Review the notebook's code for operations that might consume excessive resources. Ensure `jupyter_client` and other Jupyter-related packages are up to date.","cause":"The Jupyter kernel responsible for executing the notebook's code unexpectedly terminated or became unresponsive during startup or execution. This can be caused by resource exhaustion (e.g., memory), unhandled kernel crashes, or issues with the kernel itself.","error":"RuntimeError: Kernel died before replying to kernel_info"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":"0.10.4","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.64,"mem_mb":14.5,"disk_size":"36.1M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.61,"mem_mb":14.5,"disk_size":"36.1M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":4,"import_time_s":0.49,"mem_mb":14.5,"disk_size":"33M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.49,"mem_mb":14.5,"disk_size":"33M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.83,"mem_mb":16.1,"disk_size":"40.2M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.89,"mem_mb":16.1,"disk_size":"40.2M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.7,"import_time_s":0.72,"mem_mb":16.1,"disk_size":"37M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.68,"mem_mb":16.1,"disk_size":"37M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.95,"mem_mb":16,"disk_size":"31.5M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.99,"mem_mb":16,"disk_size":"31.5M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.1,"import_time_s":0.89,"mem_mb":16,"disk_size":"28M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.91,"mem_mb":16,"disk_size":"28M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.91,"mem_mb":16.8,"disk_size":"30.8M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.95,"mem_mb":16.8,"disk_size":"30.7M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.2,"import_time_s":0.85,"mem_mb":16.8,"disk_size":"27M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.88,"mem_mb":16.8,"disk_size":"27M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.66,"mem_mb":21.2,"disk_size":"35.9M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.66,"mem_mb":21.2,"disk_size":"35.9M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":4.8,"import_time_s":0.67,"mem_mb":21.2,"disk_size":"32M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.56,"mem_mb":21.2,"disk_size":"32M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}