Skip to main content

palitra

a.k.a. "palette" — captures the essence of the library: blending differently colored (sync/async) functions like on an artist’s palette.

It's a lightweight bridge between synchronous and asynchronous Python code, maintaining a persistent event loop in a background thread. It allows you to call async def functions directly from regular (sync) code without blocking or complex event loop reentry.

Unlike asyncio.run(), which creates and tears down a new event loop on each call, using palitra.run() eliminates that overhead — preserving async state and resources (like aiohttp sessions or database connections) across multiple calls.

⚠️ Known issues: Unexpected behaviour at cleanup in free-threaded builds.

If something breaks in your environment, please report an issue—the whole purpose of this library is to spare developers from reinventing async/sync bridges in every project. Your feedback directly helps improve its reliability and real-world compatibility.

Inspired by Running async code from sync in Python asyncio by lemon24 and related discussions such as Celery #9058.

Installation

You can install palitra from PyPI with pip or any other Python package manager (uv, poetry, etc):

pip install palitra

Features

  • ✅ Runs a persistent asyncio event loop in a background thread
  • ✅ Simple, thread-safe API for running coroutines from sync code
  • ✅ No monkey patching or global loop overrides
  • ✅ Automatic cleanup via atexit and weakref to global runner (if used)
  • ✅ Lightweight: no external dependencies

Documentation

Why does this even exist?

Usage Examples

This is not ideal, but in real-world scenarios, migrating to native non-blocking/asyncio code isn’t always possible. When stuck with sync environment, palitra lets you still use async features to get things working.

Flask with aiohttp

from flask import Flask, jsonify
import palitra
import aiohttp # better use niquests btw
import asyncio

app = Flask(__name__)

async def fetch_url(session, url):
    async with session.get(url) as response:
        return await response.json()

@app.route('/api/comments')
def get_comments():
    async def fetch_all():
        async with aiohttp.ClientSession() as session:
            urls = [
                'https://jsonplaceholder.typicode.com/comments/1',
                'https://jsonplaceholder.typicode.com/comments/2',
                'https://jsonplaceholder.typicode.com/comments/3',
            ]
            return await asyncio.gather(*[fetch_url(session, url) for url in urls])

    comments = palitra.run(fetch_all())
    return jsonify(comments)

if __name__ == '__main__':
    app.run()

Celery

import palitra
from celery import Celery
import asyncio
import time

celery_app = Celery('tasks', broker='pyamqp://guest@localhost//') #  better migrate to taskiq

async def async_processing(data: str) -> dict:
    await asyncio.sleep(0.5)  # simulated async I/O
    return {"input": data, "processed": True, "timestamp": time.time()}

@celery_app.task(name="process_async")
def sync_celery_wrapper(data: str):
    return palitra.run(async_processing(data))

Contributing

Pull requests are welcome! Please:

  • Document known issues or caveats
  • Include test coverage for new features
  • Keep the code as simple and minimal as possible
  • Prefer clarity over cleverness

Things that need more work:

  • Proper stress testing
  • Verifying thread safety in edge cases
  • Ensuring reliable shutdown under all conditions
  • Debug free-threading

License

BSD-3-Clause

Metadata

Release files for palitra 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for palitra 0.1.0
File Size Uploaded
palitra-0.1.0.tar.gz 7.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for palitra 0.1.0
File Interpreter ABI Platform
palitra-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 15.4 kB

Release files / palitra-0.1.0.tar.gz

Download URL palitra-0.1.0.tar.gz
Size 7.5 kB
Tags Source
SHA-256 checksum
How to use checksums
ab54c4e68033d6bd8d379b56c58b170aa3b8e0e5007565286135670226e620b1
BLAKE2b-256 checksum
How to use checksums
be8b0b67f982adf6d14e990fce69e90fada05a8a0b54d3ea59483a42c4f1d510
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 22, 2026.

Transparency log

Release files / palitra-0.1.0-py3-none-any.whl

Download URL palitra-0.1.0-py3-none-any.whl
Size 7.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ffd45a57e1147a291ee2bdff7c3dac281875c5225c9d854925c637c4c9a237f3
BLAKE2b-256 checksum
How to use checksums
bac2dd45b25d02d4410bb44a9f5ef79babf0b3e56712ad9fd7ec5ec48c92ecc5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 22, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page