soon

Worker decorator for background tasks re-using ThreadPoolExecutor.


License
MIT
Install
pip install soon==0.2

Documentation

Soon

Worker decorator for background tasks re-using ThreadPoolExecutor.

Installation

Soon is conveniently available via pip:

pip install soon

or installable via git clone and setup.py

git clone git@github.com:dotpot/Soon.git
sudo python setup.py install

To ensure Soon is properly installed, you can run the unittest suite from the project root:

pipenv run pytest -v 

Usage

The Soon library enables you to utilize the benefits of multi-threading with minimal concern about the implementation details.

Website fetcher example

You've collected a list of urls and are looking to download the HTML of the lot. The following is a perfectly reasonable first stab at solving the task.

urls = [
    'https://cnn.com',
    'https://news.ycombinator.com/',
    'https://stackoverflow.com/',
]

import time
import requests

def fetch(url):
    return requests.get(url)

if __name__ == "__main__":

    start = time.time()
    responses = [fetch(url) for url in urls]
    html = [response.text for response in responses]
    end = time.time()
    print("Time: %f seconds" % (end - start))

More efficient website fetcher example

Using Soon's decorator syntax, we can define a function that executes in multiple threads. Individual calls to download are non-blocking, but we can largely ignore this fact and write code identically to how we would in a synchronous paradigm.

import time
import requests

from soon import workers

@workers(5)
def fetch(url):
    return requests.get(url)

if __name__ == "__main__":
    start = time.time()
    responses = [fetch(url) for url in urls]
    html = [response.text for response in responses]
    end = time.time()
    print("Time: %f seconds" % (end - start))

We can now download websites more efficiently.


You can also optionally pass in timeout argument, to prevent hanging on a task that is not guaranteed to return.

import time

from soon import workers

@workers(1, timeout=0.1)
def timeout_error():
    time.sleep(1)

if __name__ == "__main__":
    timeout_error()