2026-02-04 14:35:08 -05:00
# Temporal Python SDK Reference
## Overview
The Temporal Python SDK (`temporalio` ) provides a fully async, type-safe approach to building durable workflows. Python 3.9+ required. Workflows run in a sandbox by default for determinism protection.
2026-02-20 18:20:51 -05:00
## Quick Demo of Temporal
**Add Dependency on Temporal: ** In the package management system of the Python project you are working on, add a dependency on `temporalio` .
2026-02-04 14:35:08 -05:00
**activities/greet.py ** - Activity definitions (separate file for performance):
2026-04-17 10:11:47 -04:00
2026-02-04 14:35:08 -05:00
``` python
from temporalio import activity
@activity.defn
2026-02-20 18:20:51 -05:00
def greet ( name : str ) - > str :
2026-02-04 14:35:08 -05:00
return f " Hello, { name } ! "
```
**workflows/greeting.py ** - Workflow definition (import activities through sandbox):
2026-04-17 10:11:47 -04:00
2026-02-04 14:35:08 -05:00
``` python
from datetime import timedelta
from temporalio import workflow
with workflow . unsafe . imports_passed_through ( ) :
from activities . greet import greet
@workflow.defn
class GreetingWorkflow :
@workflow.run
async def run ( self , name : str ) - > str :
return await workflow . execute_activity (
2026-02-18 17:08:18 -05:00
greet , name , start_to_close_timeout = timedelta ( seconds = 30 )
2026-02-04 14:35:08 -05:00
)
```
2026-04-30 16:06:59 -04:00
**worker.py ** - Worker setup (registers activity and workflow, runs indefinitely and processes tasks):
2026-04-17 10:11:47 -04:00
2026-02-04 14:35:08 -05:00
``` python
import asyncio
2026-02-20 18:20:51 -05:00
import concurrent . futures
2026-02-04 14:35:08 -05:00
from temporalio . client import Client
from temporalio . worker import Worker
2026-02-20 18:20:51 -05:00
# Import the activity and workflow from our other files
2026-02-04 14:35:08 -05:00
from activities . greet import greet
from workflows . greeting import GreetingWorkflow
async def main ( ) :
2026-02-20 18:20:51 -05:00
# Create client connected to server at the given address
# This is the default port for `temporal server start-dev`
client = await Client . connect ( " localhost:7233 " )
# Run the worker
with concurrent . futures . ThreadPoolExecutor ( max_workers = 100 ) as activity_executor :
worker = Worker (
client ,
task_queue = " my-task-queue " ,
workflows = [ GreetingWorkflow ] ,
activities = [ greet ] ,
activity_executor = activity_executor ,
2026-02-04 14:35:08 -05:00
)
2026-02-20 18:20:51 -05:00
await worker . run ( )
if __name__ == " __main__ " :
asyncio . run ( main ( ) )
```
**Start the dev server: ** Start `temporal server start-dev` in the background.
**Start the worker: ** Start `python worker.py` in the background (appropriately adjust command for your project, like `uv run python worker.py` )
**starter.py ** - Start a workflow execution:
2026-04-17 10:11:47 -04:00
2026-02-20 18:20:51 -05:00
``` python
import asyncio
from temporalio . client import Client
import uuid
# Import the workflow from the previous code
from workflows . greeting import GreetingWorkflow
async def main ( ) :
# Create client connected to server at the given address
client = await Client . connect ( " localhost:7233 " )
# Execute a workflow
result = await client . execute_workflow ( GreetingWorkflow . run , " my name " , id = str ( uuid . uuid4 ( ) ) , task_queue = " my-task-queue " )
print ( f " Result: { result } " )
2026-02-04 14:35:08 -05:00
2026-02-20 18:20:51 -05:00
if __name__ == " __main__ " :
asyncio . run ( main ( ) )
2026-02-04 14:35:08 -05:00
```
2026-02-20 18:20:51 -05:00
**Run the workflow: ** Run `python starter.py` (or uv run, etc.). Should output: `Result: Hello, my-name!` .
2026-02-04 14:35:08 -05:00
## Key Concepts
### Workflow Definition
2026-04-17 10:11:47 -04:00
2026-02-04 14:35:08 -05:00
- Use `@workflow.defn` decorator on class
2026-03-31 14:16:11 -07:00
- Put any state initialization logic in the `__init__` of your workflow class to guarantee that it happens before signals/updates arrive. If your state initialization logic requires the workflow parameters, then add the `@workflow.init` decorator and parameters to your `__init__` .
2026-02-04 14:35:08 -05:00
- Use `@workflow.run` on the entry point method
- Must be async (`async def` )
- Use `@workflow.signal` , `@workflow.query` , `@workflow.update` for handlers
### Activity Definition
2026-04-17 10:11:47 -04:00
2026-02-04 14:35:08 -05:00
- Use `@activity.defn` decorator
- Can be sync or async functions
- **Default to sync activities** - safer and easier to debug
- Sync activities need `activity_executor` (ThreadPoolExecutor)
- Async activities require async-safe libraries throughout (e.g., `aiohttp` not `requests` )
See `sync-vs-async.md` for detailed guidance on choosing between sync and async.
### Worker Setup
2026-04-17 10:11:47 -04:00
2026-02-04 14:35:08 -05:00
- Connect client, create Worker with workflows and activities
2026-02-20 18:20:51 -05:00
- Run the worker
2026-02-04 14:35:08 -05:00
- Activities can specify custom executor
2026-02-20 18:20:51 -05:00
### Determinism
2026-02-04 14:35:08 -05:00
2026-02-20 18:20:51 -05:00
**Workflow code must be deterministic! ** . All sources of non-determinism should either use Temporal-provided actions or (primarily) be defined in Activities. Read `references/core/determinism.md` and `references/python/determinism.md` to understand more.
2026-02-04 14:35:08 -05:00
## File Organization Best Practice
**Keep Workflow definitions in separate files from Activity definitions. ** The Python SDK sandbox reloads Workflow definition files on every execution for determinism protection. Minimizing file contents improves Worker performance.
```
my_temporal_app/
├── workflows/
│ └── greeting.py # Only Workflow classes
├── activities/
│ └── translate.py # Only Activity functions/classes
├── worker.py # Worker setup, imports both
└── starter.py # Client code to start workflows
```
**In the Workflow file, import Activities through the sandbox: **
2026-04-17 10:11:47 -04:00
2026-02-04 14:35:08 -05:00
``` python
# workflows/greeting.py
from temporalio import workflow
with workflow . unsafe . imports_passed_through ( ) :
from activities . translate import TranslateActivities
```
## Common Pitfalls
2026-02-20 18:20:51 -05:00
1. **Non-deterministic code in workflows ** - Use activities for all non-deterministic and/or fallible code
2026-02-04 14:35:08 -05:00
2. **Blocking in async activities ** - Use sync activities or async-safe libraries only
3. **Missing executor for sync activities ** - Add `activity_executor=ThreadPoolExecutor()`
4. **Forgetting to heartbeat ** - Long activities need `activity.heartbeat()`
5. **Using gevent ** - Incompatible with SDK
6. **Using `print()` in workflows ** - Use `workflow.logger` instead for replay-safe logging
2026-03-07 09:41:32 -05:00
7. **Mixing Workflows and Activities in same file ** - Causes unnecessary reloads, hurts performance, bad structure
8. **Forgetting to wait on activity calls ** - `workflow.execute_activity()` is async; you must eventually await it (directly or via `asyncio.gather()` for parallel execution)
2026-02-20 18:20:51 -05:00
## Writing Tests
See `references/python/testing.md` for info on writing tests.
2026-02-04 14:35:08 -05:00
## Additional Resources
### Reference Files
2026-04-17 10:11:47 -04:00
2026-02-27 17:51:37 -05:00
- **`references/python/patterns.md` ** - Signals, queries, child workflows, saga pattern, etc.
2026-02-20 18:20:51 -05:00
- **`references/python/determinism.md` ** - Sandbox behavior, safe alternatives, pass-through pattern, history replay
- **`references/python/gotchas.md` ** - Python-specific mistakes and anti-patterns
- **`references/python/error-handling.md` ** - ApplicationError, retry policies, non-retryable errors, idempotency
- **`references/python/observability.md` ** - Logging, metrics, tracing, Search Attributes
- **`references/python/testing.md` ** - WorkflowEnvironment, time-skipping, activity mocking
- **`references/python/sync-vs-async.md` ** - Sync vs async activities, event loop blocking, executor configuration
2026-02-27 17:51:37 -05:00
- **`references/python/advanced-features.md` ** - Schedules, worker tuning, and more
2026-02-20 18:20:51 -05:00
- **`references/python/data-handling.md` ** - Data converters, Pydantic, payload encryption
- **`references/python/versioning.md` ** - Patching API, workflow type versioning, Worker Versioning
2026-02-23 15:04:18 -05:00
- **`references/python/determinism-protection.md` ** - Python sandbox specifics, forbidden operations, pass-through imports
2026-02-20 18:20:51 -05:00
- **`references/python/ai-patterns.md` ** - LLM integration, Pydantic data converter, AI workflow patterns
2026-05-13 13:46:18 -04:00
### Python Integrations
For Python-specific third-party integrations (OpenAI Agents SDK, Google ADK, etc.), see `references/integrations.md` and filter for Python. Reference files live under `references/python/integrations/` .