Skip to main content

asynctor

Python Versions LatestVersionInPypi GithubActionResult pre-commit Coverage Status Mypy coverage Ruff

Some async functions that using anyio, and toolkit for excel read.

Installation

$ pip install asynctor
---> 100%
Successfully installed asynctor

with extras:

pip install "asynctor[xlsx,redis,fastapi]"

Or by pdm:

pdm add "asynctor[redis]"

Or by uv:

uv add asynctor

Or install the latest from github

uv pip install "asynctor @git+https://github.com/waketzheng/asynctor"

Or install by ssh

uv pip install "asynctor[redis] @git+ssh://git@github.com/waketzheng/asynctor.git"

Usage

  • Async function that compare asyncio but use anyio: bulk_gather/gather/run
>>> import asynctor
>>> async def foo():
...     return 1
...
>>> await asynctor.bulk_gather([foo(), foo()], limit=200)
(1, 1)
>>> await asynctor.gather(foo(), foo())
(1, 1)
>>> asynctor.run(gather(foo(), foo()))
(1, 1)
  • run_async: start a new thread to run async function and get result of it
>>> from asynctor import run_async
>>> async def foo(a=1):
...     return a
...
>>> run_async(foo) == run_async(foo()) == run_async(foo, 1) == 1
True
  • timeit/Timer
>>> import time
>>> import anyio
>>> from asynctor import Timer, timeit
>>> @timeit
... async def sleep_test():
...     await anyio.sleep(3)
...
>>> await sleep()
sleep_test Cost: 3.0 seconds

>>> @timeit
... def sleep_test2():
...     time.sleep(3.1)
...
>>> sleep_test2()
sleep_test2 Cost: 3.1 seconds
>>> with Timer('Sleeping'):
...     sleep()
...
Sleeping Cost: 3.0 seconds
>>> from loguru import logger
>>> with Timer('doing sth', verbose=False) as t:
...     time.sleep(0.222)
...
>>> logger.debug(t)
2026-06-10 12:07:55.658 | DEBUG    | __main__:<module>:1 - doing sth Cost: 0.2 seconds
>>> Timer.beijing_now()
datetime.datetime(2026, 6, 10, 12, 9, 1, 577094, tzinfo=asynctor.timing.ZoneInfo(key='Asia/Shanghai'))
  • AioRedis

pip install "asynctor[redis]"

from asynctor.contrib.fastapi import AioRedisDep, register_aioredis
from fastapi import FastAPI

app = FastAPI()
register_aioredis(app)


@app.get("/")
async def root(redis: AioRedisDep) -> list[str]:
    return await redis.keys()


@app.get("/redis")
async def get_value_from_redis_by_key(redis: AioRedisDep, key: str) -> str:
    value = await redis.get(key)
    if not value:
        return ""
    return value.decode()
  • Async Test Fixtures

pip install "asynctor[testing]"

import pytest
from asynctor.testing import AsyncClient, anyio_backend_fixture, async_client_fixture

from main import app  # isinstance(app, FastAPI)

anyio_backend = anyio_backend_fixture()
client = async_client_fixture(app)


@pytest.mark.anyio
async def test_api(client: AsyncClient):
    response = await client.get("/")
    assert response.status_code == 200
  • runserver/config_access_log/add_timing_middleware for fastapi projects

pip install "asynctor[fastapi]"

from asynctor.contrib.fastapi import add_timing_middleware, config_access_log, runserver
from fastapi import FastAPI

app = FastAPI()
config_access_log()
add_timing_middleware(app)


if __name__ == "__main__":
    runserver()
  • Read Excel File

pandas/openpyxl is required, can be installed with xlsx extra: pip install "asynctor[xlsx]"

>>> from asynctor.xlsx import load_xlsx
>>> await load_xlsx('tests/demo.xlsx')
[{'Column1': 'row1-\\t%c', 'Column2\nMultiLines': 0, 'Column 3': 1, 4: ''}, {'Column1': 'r2c1\n00', 'Column2\nMultiLines': 'r2 c2', 'Column 3': 2, 4: ''}]
  • json

Auto use orjson if it's installed, fallback to standard json module.

>>> from asynctor.jsons import json_dump_bytes
>>> json_dump_bytes({'a': 1})
b'{"a":1}'
>>> json_dump_bytes({'a': 1}, pretty=True)
b'{\n  "a": 1\n}'
  • utils
  1. load_bool
>>> from asynctor.utils import load_bool
>>> load_bool('NOT_EXIST')
False
>>> import os
>>> os.environ['MY_ENV'] = '0'
>>> load_bool('MY_ENV')
False
>>> os.environ['MY_ENV'] = '1'
>>> load_bool('MY_ENV')
True
  1. ExtendSyspath
>>> import conftest
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    import conftest
ModuleNotFoundError: No module named 'conftest'
>>> from pathlib import Path
>>> from asynctor.utils import ExtendSyspath
>>> with ExtendSyspath('tests'):
...     import conftest
...
>>> Path(conftest.__file__).relative_to(Path.cwd()).as_posix()
'tests/conftest.py'

Download files

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

Source Distribution

asynctor-0.15.0.tar.gz (52.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

asynctor-0.15.0-py3-none-any.whl (57.3 kB view details)

Uploaded Python 3

File details

Details for the file asynctor-0.15.0.tar.gz.

File metadata

  • Download URL: asynctor-0.15.0.tar.gz
  • Upload date:
  • Size: 52.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for asynctor-0.15.0.tar.gz
Algorithm Hash digest
SHA256 903fd27327241cdd6dcfa86bec1ce8b8d1c55890c5f69f68823e315d2e722d7c
MD5 255a50f73470c05507c3ced21667e2bc
BLAKE2b-256 9a33a16bd33102f94fc45bedfad0f785ba4b80c8d59643245055aa7c92fa027d

See more details on using hashes here.

File details

Details for the file asynctor-0.15.0-py3-none-any.whl.

File metadata

  • Download URL: asynctor-0.15.0-py3-none-any.whl
  • Upload date:
  • Size: 57.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for asynctor-0.15.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1e88aef60e2542ec28214fd3a0a5dc751c41f23481a6c98fb79333a4c88098be
MD5 0f443e20b464891a4cc8d1f73c6baec0
BLAKE2b-256 0209c615e771cd80601c5837fbec5a51e3b658c8c8e99dfb7be01f9910349c52

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.15.0 This release

2 files

0.14.0

2 files

0.13.3

2 files

0.13.2

2 files

0.13.1

2 files

0.13.0

2 files

0.12.12

2 files

0.12.11

2 files

0.12.10

2 files

0.12.9

2 files

0.12.8

2 files

0.12.7

2 files

0.12.6

2 files

0.12.5

2 files

0.12.4

2 files

0.12.3

2 files

0.12.2

2 files

0.12.1

2 files

0.12.0

2 files

0.11.9

2 files

0.11.8

2 files

0.11.7

2 files

0.11.6

2 files

0.11.5

2 files

0.11.4

2 files

0.11.3

2 files

0.11.2

2 files

0.11.1

2 files

0.11.0

2 files

0.10.3

2 files

0.10.2

2 files

0.10.1

2 files

0.10.0

2 files

0.9.1

2 files

0.9.0

2 files

0.8.8

2 files

0.8.7

2 files

0.8.6

2 files

0.8.5

2 files

0.8.4

2 files

0.8.3

2 files

0.8.2

2 files

0.8.1

2 files

0.8.0

2 files

0.7.2

2 files

0.7.1

2 files

0.7.0

2 files

0.6.9

2 files

0.6.8

2 files

0.6.7

2 files

0.6.6

2 files

0.6.5

2 files

0.6.4

2 files

0.6.3

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.5

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page