The v2 model (current default for new Python function apps):

```python
import azure.functions as func
import logging

app = func.FunctionApp()

@app.service_bus_queue_trigger(arg_name="msg",
    queue_name="[queue]",
    connection="[CONNECTION]_fullyQualifiedNamespace")
def process_queue(msg: func.ServiceBusMessage):
    logging.info("got: %s", msg.get_body().decode())
```

Traps:

- **v1 vs v2 mixing.** If a `function.json` exists next to decorated code, the host gets confused. v2 = decorators only, no function.json files. Check the folder for strays when porting.
- **FUNCTIONS_WORKER_RUNTIME must be `python`.** Deploy a Python app to a function app whose setting says `node` and every invocation 500s with a worker error. Verify in app settings first.
- **Connection naming.** `connection="[CONNECTION]_fullyQualifiedNamespace"` with an app setting named `[CONNECTION]__fullyQualifiedNamespace` tells the trigger to use identity (managed identity / DefaultAzureCredential chain) instead of a connection string. The legacy pattern is a plain connection string in `[CONNECTION]`; prefer the identity form.
- **Extension bundle.** Triggers other than HTTP/Timer need the extension bundle (`host.json` with `extensionBundle` id `Microsoft.Azure.Functions.ExtensionBundle`). Missing bundle = "binding type not registered" errors.
- **Local testing.** `func start` runs the host locally. Azurite (storage emulator) covers the storage-backed triggers; for Service Bus locally you need a real namespace or the emulator story for your binding.

Verify: `func start`, trigger the function (HTTP curl or drop a queue message), confirm the invocation log line, then deploy with `func azure functionapp publish` and re-trigger in Azure.