Getting Started

This tutorial walks you through installing Pynenc, defining a task, executing it, and retrieving its result. By the end you will have a working distributed task running locally.

Prerequisites

  • Python 3.11 or later

  • pip (or any Python package manager)

Step 1: Install Pynenc

pip install pynenc

This installs the core package with the built-in Memory and SQLite backends.

Step 2: Define a Task

Create a file named tasks.py:

from pynenc import Pynenc

app = Pynenc()

@app.task
def add(x: int, y: int) -> int:
    return x + y

Important

Tasks cannot be defined in modules that run as __main__ (e.g., scripts executed with python tasks.py). Define tasks in importable modules and reference the app object from elsewhere. See the Frequently Asked Questions for details on this limitation.

Step 3: Run Synchronously (Dev Mode)

The fastest way to test is synchronous execution. Set the environment variable:

export PYNENC__DEV_MODE_FORCE_SYNC_TASKS=True

Then in a Python session or script (separate from tasks.py):

from tasks import add

result = add(1, 2).result
print(result)  # 3

The task runs in the calling thread. No runner process is needed.

Step 4: Run with a Runner

For actual distributed execution, start a runner in one terminal:

pynenc runner start

The CLI auto-discovers the app when the current directory contains exactly one importable Python file with a Pynenc() instance. In this tutorial that is tasks.py. If a project has more than one app, or if you run the command from another directory, pass it explicitly:

pynenc --app tasks.app runner start

In another terminal or script:

from tasks import add

invocation = add(1, 2)
print(invocation.result)  # blocks until the runner executes the task

The runner picks up the task from the broker, executes it, and stores the result in the state backend.

Step 5: Use the Builder for Programmatic Setup

Instead of environment variables, configure Pynenc with the PynencBuilder:

from pynenc.builder import PynencBuilder

app = (
    PynencBuilder()
    .app_id("my_app")
    .memory()
    .dev_mode(force_sync_tasks=True)
    .build()
)

@app.task
def multiply(x: int, y: int) -> int:
    return x * y

result = multiply(3, 4).result
print(result)  # 12

Step 6: Switch to a Production Backend

Install a backend plugin and update your configuration. Example with Redis:

pip install pynenc-redis
# pyproject.toml
[tool.pynenc]
app_id = "my_app"
orchestrator_cls = "RedisOrchestrator"
broker_cls = "RedisBroker"
state_backend_cls = "RedisStateBackend"
runner_cls = "MultiThreadRunner"

Or with the builder:

app = (
    PynencBuilder()
    .app_id("my_app")
    .redis(url="redis://localhost:6379")
    .multi_thread_runner(min_threads=2, max_threads=8)
    .build()
)

Start the runner:

pynenc runner start

Your tasks now route through Redis.

Step 7: Launch the Monitor

Install the monitoring extra and start Pynmon:

pip install pynenc[monitor]
pynenc monitor

If more than one app is available, choose one with --app tasks.app.

Open http://localhost:8000 to see invocations, runners, and task timelines.

Next Steps