> ## Documentation Index
> Fetch the complete documentation index at: https://docs.siftd.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Python Cells

Python cells allow you to execute arbitrary Python code in the context of the notebook session.
You have access to the full Python standard library and common packages.
You can access cell output variables that were set by other cell types.
The cells support custom visualization and data processing capabilities.
Additionally, you can integrate with external APIs and databases.

## Variables

You can reference variables set by other python cells on the global scope.

### Cell Results

All cells - with the exception of Markdown and Python cells, set their output variable ot a [CellResult](/python-api/cell-result) object.

## Output

Ways to output information from a python cell:

* Print to stdout/stderr
* Display objects via `IPython.display.display()`
* Return a display object
* Return a `CellResult` object
* Raise an exception

## Examples

Execute arbitrary Python code for custom logic:

```python theme={null}
import pandas as pd
import json
from datetime import datetime, timedelta

# Process error rate data from previous cell
df = pd.DataFrame(splunk_1)
threshold = df['error_rate'].mean() + (2 * df['error_rate'].std())

# Flag services exceeding threshold
problem_services = df[df['error_rate'] > threshold]
print(f"Found {len(problem_services)} services above threshold")
```

## Cell Parameters (@param)

**NOTE: See [Form Cells](./form-cells) for the preferred method of adding dynamic user inputs**

Python cells support inline parameter definitions using the `@param` comment syntax. Parameters create interactive form inputs that users can modify before running the cell, without editing the code directly.

Use `@param` when you need to parameterize a single cell's behavior. For inputs that need to be shared across multiple cells, use [form cells](./form-cells) instead.

### Basic Syntax

```python theme={null}
variable = default_value # @param {type:"type_name"}
```

Parameters must be defined at the top of the cell, after any import statements.

### Supported Types

#### String

```python theme={null}
api_url = 'https://api.example.com' # @param {type:"string"}
```

With additional options:

```python theme={null}
service_name = '' # @param {type:"string", label:"Service Name", description:"Enter the service to query", placeholder:"api-gateway"}
```

#### Dropdown (Static Options)

Provide a JSON array of choices:

```python theme={null}
environment = 'production' # @param ["development", "staging", "production"]
```

The default value should be one of the choices. If omitted or invalid, the first choice is used.

#### Boolean

```python theme={null}
verbose = True # @param {type:"boolean"}
show_details = False # @param {type:"boolean", label:"Show Details"}
```

#### Number

For integers:

```python theme={null}
max_results = 100 # @param {type:"integer"}
timeout = 30 # @param {type:"integer", min:1, max:300}
```

For floating-point numbers:

```python theme={null}
threshold = 0.75 # @param {type:"number", min:0.0, max:1.0}
```

#### Secret

Creates a dropdown of available secrets in the workspace:

```python theme={null}
api_key_name = '' # @param {type:"secret", label:"API Key"}

# Use the secret value
api_key = SpinSecrets.get_secret(api_key_name)
```

#### Connection

Creates a dropdown of available connections:

```python theme={null}
# Show all connections
connection_name = '' # @param {type:"connection"}

# Filter by connection scheme(s)
db_connection = '' # @param ["postgres", "mysql"] {type:"connection"}
monitoring_connection = '' # @param ["ddog", "prometheus"] {type:"connection"}
```

### Parameter Options

| Option        | Description                                                                      |
| ------------- | -------------------------------------------------------------------------------- |
| `type`        | Parameter type: `string`, `boolean`, `integer`, `number`, `secret`, `connection` |
| `label`       | Display label for the form input                                                 |
| `description` | Help text shown below the input                                                  |
| `placeholder` | Placeholder text for string inputs                                               |
| `min`         | Minimum value for number/integer types                                           |
| `max`         | Maximum value for number/integer types                                           |
| `required`    | Whether the field must have a value (`true`/`false`)                             |

### Dynamic Dropdowns with Selectors

For dropdowns populated dynamically from data, use selectors. Selectors must be created in a prior cell using `SpinContext.create_selector()`.

**Cell 1:** Create the selector

```python theme={null}
# Fetch available options from an API or compute them
regions = ["us-east-1", "us-west-2", "eu-west-1"]

# Create a selector for use in subsequent cells
SpinContext.create_selector("available_regions", regions)

# Selectors can also use dictionaries for value/label pairs
SpinContext.create_selector("region_labels", {
    "us-east-1": "US East (N. Virginia)",
    "us-west-2": "US West (Oregon)",
    "eu-west-1": "EU (Ireland)"
})
```

**Cell 2:** Use the selector in a parameter

```python theme={null}
region = '' # @param {selector_name:"available_regions"}

# Or with labels
region = '' # @param {selector_name:"region_labels"}
```

Selectors cannot be created and used in the same cell.

### Complete Example

```python theme={null}
# Parameters section - define all inputs at the top
api_url = 'https://api.example.com' # @param {type:"string", label:"API URL"}
api_key_name = '' # @param {type:"secret", label:"API Key"}
environment = 'production' # @param ["development", "staging", "production"]
max_results = 100 # @param {type:"integer", min:1, max:1000}
verbose = False # @param {type:"boolean"}

# Get the actual secret value
api_key = SpinSecrets.get_secret(api_key_name)

# Use the parameters in your code
import requests

headers = {"Authorization": f"Bearer {api_key}"}
params = {"env": environment, "limit": max_results}

response = requests.get(f"{api_url}/data", headers=headers, params=params)
data = response.json()

if verbose:
    SpinLog.info(f"Retrieved {len(data)} records from {environment}")

CellResult.set_py_result(data)
```

## Packages

The following python packages are pre-installed in the spin runtime container.

| Package              | Version  | Purpose                      |
| -------------------- | -------- | ---------------------------- |
| datadog-api-client   | ^2.29.0  | Datadog integration          |
| pyyaml               | ^6.0.2   | YAML parsing                 |
| splunk-sdk           | ^2.1.0   | Splunk integration           |
| fastapi              | ^0.100.0 | API framework                |
| httpx                | ^0.25.0  | HTTP client                  |
| uvicorn              | ^0.25.0  | ASGI server                  |
| websockets           | ^11.0.0  | WebSocket support            |
| jupyter-client       | ^8.0.0   | Jupyter kernel communication |
| notebook             | ^7.0.0   | Jupyter notebook             |
| cryptography         | ^42.0.0  | Crypto operations            |
| pyjwt                | ^2.10.1  | JWT handling                 |
| openai               | ^1.91.0  | OpenAI API client            |
| sqlalchemy           | ^2.0.0   | SQL toolkit/ORM              |
| pandas               | ^2.2.0   | Data analysis                |
| psycopg2-binary      | ^2.9.0   | PostgreSQL driver            |
| pymysql              | ^1.1.0   | MySQL driver                 |
| clickhouse-connect   | ^0.9.0   | ClickHouse driver            |
| apscheduler          | ^3.10.4  | Task scheduling              |
| boto3                | ^1.28.0  | AWS SDK                      |
| google-cloud-storage | ^3.7.0   | GCS SDK                      |

### Installing additional packages and utility

Additional packages can be installed by using a shell cell in any notebook to run pip install.  E.g.

```bash theme={null}
pip install my_new_package
```

Packages installed this way will persist across notebooks and sessions but may need to be reinstalled if the runtime is restarted or a new version is pulled.

### Custom Runtime Images

To create a custom image with a python package (or additional other utility) pre-installed, use a custom Dockerfile e.g.

```
FROM ghcr.io/siftd/spin-runtime:latest-prod

# pip install directly
RUN pip install my_new_package another_new_package

# Or use a requirements.txt file (must copy to the container first)
COPY requirements.txt
RUN pip install requirements.txt

# install kcat package using apt.  
apt install -y kcat
```
