Skip to main content

A lightweight library for allowing async functions to be called in a synchronous manner.

Project description

anysync

A lightweight library for allowing async functions to be called in a synchronous manner.

import asyncio
from anysync import anysync


@anysync
async def f():
    return 42


def test_sync():
    assert f().run() == 42


async def test_async():
    assert await f() == 42


test_sync()
asyncio.run(test_async())

anysync works by wrapping coroutines returned by async functions in an AnySync object that can both be awaited and executed synchronously when calling its run() method.

from anysync import AnySync


async def f():
    return 42


coro = f()
assert AnySync(coro).run() == 42

Comparison with asyncio.run

Unlike asyncio.run, an AnySync object can be run() even if an event loop is already running.

For example, the following code will raise a RuntimeError:

import asyncio


async def f():
    return 42


async def test_async():
    assert asyncio.run(f()) == 42


asyncio.run(test_async())

However, with anysync, the following code will work as expected:

import asyncio
from anysync import anysync


@anysync
async def f():
    return 42


async def test_async():
    assert f().run() == 42


asyncio.run(test_async())

This is accomplished by running the underlying coroutine in a separate thread.

Comparison with unsync

anysync is similar to unsync in that it allows async functions to be called synchronously when needed. The main differences are that anysync works with type checkers, is lighter weight, and works with other async libraries like trio and curio via anyio.

Comparison with automatic detection

The other approach to dealing with the challenges of mixing synchronous and asynchronous code is to automatically infer whether a function should be run synchronously based on whether it is being run in an async context. This approach is taken by libraries like Prefect's sync_compatible decorator. The main downside is that the behavior of the function changes dynamically depending on the context which can lead to unexpected behavior.

For example, the code below works as expected beca

from prefect.utilities.asyncutils import sync_compatible


@sync_compatible
async def request():
    ...
    return "hello"


def work():
    response = request()
    ...
    return response.upper()


def test_sync():
    assert work() == "HELLO"


test_sync()

However, if we now call work() from an async context, the behavior changes.

import asyncio


async def test_async():
    assert work() == "HELLO"  # AttributeError: 'coroutine' object has no attribute 'upper'


asyncio.run(test_async())

Because work() is now being called from an async context, request() automatically returns a coroutine object which causes work() to fail.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

anysync-0.1.0.tar.gz (4.4 kB view details)

Uploaded Source

Built Distribution

anysync-0.1.0-py3-none-any.whl (4.0 kB view details)

Uploaded Python 3

File details

Details for the file anysync-0.1.0.tar.gz.

File metadata

  • Download URL: anysync-0.1.0.tar.gz
  • Upload date:
  • Size: 4.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.27.0

File hashes

Hashes for anysync-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3f38048275b9efd8ac2e0b41514e88d45e9f656b22f286c407386c62d21b1cec
MD5 4964942b2961a0f0c51e4330fce02040
BLAKE2b-256 90715fec501efa799050cbcf8d385864c7238814070388e316d1aa078c8928cc

See more details on using hashes here.

File details

Details for the file anysync-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: anysync-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 4.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-httpx/0.27.0

File hashes

Hashes for anysync-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 497de68f5416d3e6bb8d0eb6f819a5dc351955638e8efafb491917d0ac914b6f
MD5 25b6198929455470e033f346f8906c2b
BLAKE2b-256 ed764f3b7f4cf2d1a5d185b5f6e4d84d7bc6fa3e8177ab07838f5b5f4279ad2b

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page