unsync

Pythons async-landskap

asyncio

threading

multiprocessing

C / Cython

I/O-bound

CPU-bound

HÃ¥ndter flere oppgaver samtidig

Gjør flere oppgaver i parallell

Gjør async programmering enklere

trio

unsync

Problem 1

Mye boiler plate

import asyncio

async def just_get_this_done():
    await do_io_stuff()

async def and_this():
    await do_io_stuff()

def annoying_boiler_plate():
    loop = asyncio.get_event_loop()
    future = asyncio.gather(just_get_this_done(), and_this())
    loop.run_until_complete(future)

if __name__ == '__main__':
    annoying_boiler_plate()
from concurrent.futures import ProcessPoolExecutor

def just_get_this_done():
    do_cpu_stuff()

def and_this():
    do_cpu_stuff()

def annoying_boiler_plate():
    with ProcessPoolExecutor() as ppe:
        ppe.submit(just_get_this_done),
        ppe.submit(and_this)

if __name__ == '__main__':
    annoying_boiler_plate()
from concurrent.futures import ThreadPoolExecutor

def just_get_this_done():
    do_io_stuff()

def and_this():
    do_io_stuff()

def annoying_boiler_plate():
    with ThreadPoolExecutor() as tpe:
        tpe.submit(just_get_this_done)
        tpe.submit(and_this)

if __name__ == '__main__':
    annoying_boiler_plate()

asyncio

threading

multiprocessing

Problem 2

Ulike interfaces

result = ProcessPoolExecutor()
         .submit(my-func, args)
         .result()
result = await my_func(args)

vs.

Problem 3

Krunglete å kombinere
asyncio, threading og multiprocessing

from concurrent.futures import ProcessPoolExecutor
import asyncio

async def extract():
    return 21

def transform(input):
    return input * 2

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    extracted_result = loop.run_until_complete(extract())

    with ProcessPoolExecutor() as executor:
        transformed = executor.submit(transform, extracted_result)

    print(transformed.result())

unsync

En decorator som kan brukes på async- og vanlige funksjoner

from unsync import unsync

@unsync()
def just_get_this_done():
    do_stuff()

@unsync()
def and_this():
    do_stuff()

@unsync()
async def and_this_too():
    await do_stuff()

if __name__ == '__main__':
    just_get_this_done()
    and_this()
    and_this_too()

Med cpu_bound=True kjøres funksjonen i en separat prosess

from unsync import unsync

@unsync()
def just_get_this_done():
    do_stuff()

@unsync(cpu_bound=True)
def and_this():
    do_stuff()

@unsync()
async def and_this_too():
    await do_stuff()

if __name__ == '__main__':
    just_get_this_done()
    and_this()
    and_this_too()

Felles interface for henting av resultat

@unsync()
def just_get_this_done():
    return do_stuff()

@unsync(cpu_bound=True)
def and_this():
    return do_stuff()

@unsync()
async def and_this_too():
    return await do_stuff()

if __name__ == '__main__':
    tasks = [
        just_get_this_done()
        and_this()
        and_this_too()
    ]

    results = [task.result() for task in tasks]

Støtter chaining

from unsync import unsync, Unfuture

@unsync()
async def extract():
    return 21

@unsync(cpu_bound=True)
def transform(input: Unfuture):
    return input.result() * 2

@unsync()
def load(input: Unfuture):
    with open('the_answer.txt', 'w') as file:
        file.write(input.result())

extract().then(transform).then(load).result()

# TypeError: cannot pickle '_asyncio.Task' object

(men ikke med cpu_bound=True)

from unsync import unsync, Unfuture

@unsync()
async def extract():
    return 21

@unsync()
def transform(input: Unfuture):
    return input.result() * 2

@unsync()
def load(input: Unfuture):
    with open('the_answer.txt', 'w') as file:
        file.write(input.result())

extract().then(transform).then(load).result()

Unfuture som wrapper for asyncio.Task og concurrent.futures.Future

>>> @unsync()
... async def coro():
...     pass
...
>>> future = coro()
>>>
>>> type(future)
<class 'unsync.unsync.Unfuture'>
>>> type(future.future)
<class '_asyncio.Task'>
>>> type(future.concurrent_future)
<class 'concurrent.futures._base.Future'>
>>> future.__await__
<bound method Unfuture.__iter__ of <unsync.unsync.Unfuture object at 0x7f72e250bf70>>

Demo

Demo

async uten unsync

async med unsync

unsync med chaining

sync

Demo

Ulemper med unsync

  • Unfutures starter umiddelbart
  • Lite kontroll pÃ¥ køen

Slutt

kurs:

unsync:

demo-kode:

dunsync: