Skip to main content

Zero-dependency Python package for easy throttling with asyncio support

Project description

Throttler

Python PyPI License: MIT

Python Tests codecov

Zero-dependency Python package for easy throttling with asyncio support.

Demo

📝 Table of Contents

🎒 Install

Just

pip install throttler

🛠 Usage Examples

All run-ready examples are here.

Throttler and ThrottlerSimultaneous

Throttler:

Context manager for limiting rate of accessing to context block.

from throttler import Throttler

# Limit to three calls per second
t = Throttler(rate_limit=3, period=1.0)
async with t:
    pass

Or

import asyncio

from throttler import throttle

# Limit to three calls per second
@throttle(rate_limit=3, period=1.0)
async def task():
    return await asyncio.sleep(0.1)

ThrottlerSimultaneous:

Context manager for limiting simultaneous count of accessing to context block.

from throttler import ThrottlerSimultaneous

# Limit to five simultaneous calls
t = ThrottlerSimultaneous(count=5)
async with t:
    pass

Or

import asyncio

from throttler import throttle_simultaneous

# Limit to five simultaneous calls
@throttle_simultaneous(count=5)
async def task():
    return await asyncio.sleep(0.1)

Simple Example

import asyncio
import time

from throttler import throttle


# Limit to two calls per second
@throttle(rate_limit=2, period=1.0)
async def task():
    return await asyncio.sleep(0.1)


async def many_tasks(count: int):
    coros = [task() for _ in range(count)]
    for coro in asyncio.as_completed(coros):
        _ = await coro
        print(f'Timestamp: {time.time()}')

asyncio.run(many_tasks(10))

Result output:

Timestamp: 1585183394.8141203
Timestamp: 1585183394.8141203
Timestamp: 1585183395.830335
Timestamp: 1585183395.830335
Timestamp: 1585183396.8460555
Timestamp: 1585183396.8460555
...

API Example

import asyncio
import time

import aiohttp

from throttler import Throttler, ThrottlerSimultaneous


class SomeAPI:
    api_url = 'https://example.com'

    def __init__(self, throttler):
        self.throttler = throttler

    async def request(self, session: aiohttp.ClientSession):
        async with self.throttler:
            async with session.get(self.api_url) as resp:
                return resp

    async def many_requests(self, count: int):
        async with aiohttp.ClientSession() as session:
            coros = [self.request(session) for _ in range(count)]
            for coro in asyncio.as_completed(coros):
                response = await coro
                print(f'{int(time.time())} | Result: {response.status}')


async def run():
    # Throttler can be of any type
    t = ThrottlerSimultaneous(count=5)        # Five simultaneous requests
    t = Throttler(rate_limit=10, period=3.0)  # Ten requests in three seconds

    api = SomeAPI(t)
    await api.many_requests(100)

asyncio.run(run())

Result output:

1585182908 | Result: 200
1585182908 | Result: 200
1585182908 | Result: 200
1585182909 | Result: 200
1585182909 | Result: 200
1585182909 | Result: 200
1585182910 | Result: 200
1585182910 | Result: 200
1585182910 | Result: 200
...

ExecutionTimer

Context manager for time limiting of accessing to context block. Simply sleep period secs before next accessing, not analog of Throttler. Also it can align to start of minutes.

import time

from throttler import ExecutionTimer

et = ExecutionTimer(60, align_sleep=True)

while True:
    with et:
        print(time.asctime(), '|', time.time())

Or

import time

from throttler import execution_timer

@execution_timer(60, align_sleep=True)
def f():
    print(time.asctime(), '|', time.time())

while True:
    f()

Result output:

Thu Mar 26 00:56:17 2020 | 1585173377.1203406
Thu Mar 26 00:57:00 2020 | 1585173420.0006166
Thu Mar 26 00:58:00 2020 | 1585173480.002517
Thu Mar 26 00:59:00 2020 | 1585173540.001494

Timer

Context manager for pretty printing start, end, elapsed and average times.

import random
import time

from throttler import Timer

timer = Timer('My Timer', verbose=True)

for _ in range(3):
    with timer:
        time.sleep(random.random())

Or

import random
import time

from throttler import timer

@timer('My Timer', verbose=True)
def f():
    time.sleep(random.random())

for _ in range(3):
    f()

Result output:

#1 | My Timer | begin: 2020-03-26 01:46:07.648661
#1 | My Timer |   end: 2020-03-26 01:46:08.382135, elapsed: 0.73 sec, average: 0.73 sec
#2 | My Timer | begin: 2020-03-26 01:46:08.382135
#2 | My Timer |   end: 2020-03-26 01:46:08.599919, elapsed: 0.22 sec, average: 0.48 sec
#3 | My Timer | begin: 2020-03-26 01:46:08.599919
#3 | My Timer |   end: 2020-03-26 01:46:09.083370, elapsed: 0.48 sec, average: 0.48 sec

👨🏻‍💻 Author

Ramzan Bekbulatov:

💬 Contributing

Contributions, issues and feature requests are welcome!

📝 License

This project is MIT licensed.

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

throttler-1.2.2.tar.gz (8.0 kB view details)

Uploaded Source

Built Distribution

throttler-1.2.2-py3-none-any.whl (7.6 kB view details)

Uploaded Python 3

File details

Details for the file throttler-1.2.2.tar.gz.

File metadata

  • Download URL: throttler-1.2.2.tar.gz
  • Upload date:
  • Size: 8.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.11.0

File hashes

Hashes for throttler-1.2.2.tar.gz
Algorithm Hash digest
SHA256 d54db406d98e1b54d18a9ba2b31ab9f093ac64a0a59d730c1cf7bb1cdfc94a58
MD5 5ad268f372fc87c99b3d32cdcd5dc151
BLAKE2b-256 b422638451122136d5280bc477c8075ea448b9ebdfbd319f0f120edaecea2038

See more details on using hashes here.

File details

Details for the file throttler-1.2.2-py3-none-any.whl.

File metadata

  • Download URL: throttler-1.2.2-py3-none-any.whl
  • Upload date:
  • Size: 7.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.11.0

File hashes

Hashes for throttler-1.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 fc6ae612a2529e01110b32335af40375258b98e3b81232ec77cd07f51bf71392
MD5 ad1197835528da48f2bf2f0fbe9575a3
BLAKE2b-256 dfd436bf6010b184286000b2334622bfb3446a40c22c1d2a9776bff025cb0fe5

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