Skip to main content

Parallely - Parallel Python made simple

pypi License wheel python Test Suite Coverage Status docs

Installation

To install this library, all you have to do is write pip install parallely. The library is really simple with just 3 functions. However, if needed, you can find the docs at ReadTheDocs

Overview

Dealing with multi-threading, parallel processes, and concurrent functions can be difficult in Python. A lot of boiler plate code is needed, and it is difficult to gauge whether it actually improved performance or not.

In some cases, it is necessary to tailor the program to utilize the underlying computational resources. In most cases, we just want to do the same thing many times with small alterations. In these scenarios parallely can make your life much easier.

Multi Threading

Due to the GIL multi threading is far from as useful in Python as it is in other langauges. However, when dealing with I/O intensive applications it can still be really usefull to have multiple threads waiting for a response in parallel instead of waiting for each response sequentially, if you are confused by this, there are plenty of tutorials etc. to help you out

Most of the time we just want to make a series of webrequests. In this case parallely removes all complexity of handling all the threads with a single decorator threaded. Which is easiest to explain with an example:

import time
from parallely import threaded

@threaded
def thread_function(name, duration, other_arg):
    print(f"Thread {name}: starting", other_arg)
    time.sleep(duration)
    print(f"Thread {name}: finishing", other_arg)


print("Synchronous")
thread_function(1, duration=2, other_arg="hello world")
thread_function(2, duration=1, other_arg="hello world")
# NOTICE: We can use the thread_function the exact way we would expect without any overhead

print()
print("Parallel/Asynchrous")
thread_function.map(name=[1, 2], duration=[2, 1], other_arg="hello world")
# NOTICE: the constant given to 'other_arg' is repeated in all function calls
# thread_function.map([1, 2], [2, 1], "hello world") would produce a similar result

As can be seen, the decorated function can be used like one would expect, which makes it easiest to test the function etc. However, it allso gets a .map() attribute, which can be used to run the function in a parallel manner.

Multi Processing

Working with multiple processes is one of the only ways to get around the GIL. However, this approach has all sorts of problems on its own. In many cases transferring the data between processes takes more time than the actual calculations. However, some times it can dramatically speed things up. parallely makes it just as easy to work with multiple processes as it does with threads. Simply use the decorator parallel as can be seen in the example below.

from time import time
from random import randint
from parallely import parallel


@parallel
def count_in_range(size, search_minimum, search_maximum):
    """Returns how many numbers lie within `maximum` and `minimum` in a random array"""
    rand_arr = [randint(0, 10) for _ in range(int(size))] 
    return sum([search_minimum <= n <= search_maximum for n in rand_arr])

size = 1e7

print("Sequential")
start_time = time()
for _ in range(4):
    result = count_in_range(size, search_minimum=1, search_maximum=2)
    print(result, round(time() - start_time, 2), "seconds")

print()

print("Parallel")
start_time = time()
result = count_in_range.map(size=[size, size, size, size], search_minimum=1, search_maximum=2)
print(result, round(time() - start_time, 2), "seconds")

Asynchronous

import asyncio
import time
from random import randint
from parallely import asynced


async def echo(delay, start_time):
    await asyncio.sleep(randint(0, delay))
    print(delay, round(time.time() - start_time, 1))

@asynced
async def main(counts):
    start_time = time.time()
    print(f"started at {time.strftime('%X')}")
    
    corr = []
    for count in range(counts):
        corr.append(echo(count, start_time))
        
    await asyncio.gather(*corr)

    print(f"finished at {time.strftime('%X')}")

# The asynchronous function can now be called in a synchronous manner without awiting it
main(10)

# It can also be called in a parallel manner
main.map([5, 5])

Metadata

Release files for parallely 0.2.6

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

Source distribution (sdist)

Source distribution for parallely 0.2.6
File Size Uploaded Provenance
parallely-0.2.6.tar.gz 196.4 kB Without provenance Details

Built distribution (wheel)

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

Total release size: 214.1 kB

Release files / parallely-0.2.6.tar.gz

Download URL parallely-0.2.6.tar.gz
Size 196.4 kB
Tags Source
SHA-256 checksum
How to use checksums
90cf3ed4df68568f15add4acacc4d09c5e1a254e6a18efe985676f424a8308c4
BLAKE2b-256 checksum
How to use checksums
8d0f9683812e494c74db63710402ddc2c065a2afaf9ed725fcdf095cc72e32bb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.8 CPython/3.9.7 Darwin/20.6.0

Release files / parallely-0.2.6-py3-none-any.whl

Download URL parallely-0.2.6-py3-none-any.whl
Size 17.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2855689d84a1dd95237f8d46b8cef4f063c449e5c279b3cb57ebb8eec50c4611
BLAKE2b-256 checksum
How to use checksums
72e23d9363375c6b81232072734727a8a6fec1c880b7e57219b31404b3118e1c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.8 CPython/3.9.7 Darwin/20.6.0

Security for parallely 0.2.6

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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