Asynchronous method call in Python?


I was wondering if there’s any library for asynchronous method calls in Python. It would be great if you could do something like

def longComputation():

token = longComputation()
# alternative, polling
while not token.finished():
    if token.finished():
        result = token.result()

Or to call a non-async routine asynchronously

def longComputation()

token = asynccall(longComputation())

It would be great to have a more refined strategy as native in the language core. Was this considered?

Asked By: Stefano Borini



It’s not in the language core, but a very mature library that does what you want is Twisted. It introduces the Deferred object, which you can attach callbacks or error handlers (“errbacks”) to. A Deferred is basically a “promise” that a function will have a result eventually.

Something like:

import threading

thr = threading.Thread(target=foo, args=(), kwargs={})
thr.start() # Will run "foo"
thr.is_alive() # Will return whether foo is running currently
thr.join() # Will wait till "foo" is done

See the documentation at for more details.

Answered By: Drakosha

Is there any reason not to use threads? You can use the threading class.
Instead of finished() function use the isAlive(). The result() function could join() the thread and retrieve the result. And, if you can, override the run() and __init__ functions to call the function specified in the constructor and save the value somewhere to the instance of the class.

Answered By: ondra

You can use the multiprocessing module added in Python 2.6. You can use pools of processes and then get results asynchronously with:

apply_async(func[, args[, kwds[, callback]]])


from multiprocessing import Pool

def f(x):
    return x*x

if __name__ == '__main__':
    pool = Pool(processes=1)              # Start a worker processes.
    result = pool.apply_async(f, [10], callback) # Evaluate "f(10)" asynchronously calling callback when finished.

This is only one alternative. This module provides lots of facilities to achieve what you want. Also it will be really easy to make a decorator from this.

Answered By: Lucas S.

My solution is:

import threading

class TimeoutError(RuntimeError):

class AsyncCall(object):
    def __init__(self, fnc, callback = None):
        self.Callable = fnc
        self.Callback = callback

    def __call__(self, *args, **kwargs):
        self.Thread = threading.Thread(target =, name = self.Callable.__name__, args = args, kwargs = kwargs)
        return self

    def wait(self, timeout = None):
        if self.Thread.isAlive():
            raise TimeoutError()
            return self.Result

    def run(self, *args, **kwargs):
        self.Result = self.Callable(*args, **kwargs)
        if self.Callback:

class AsyncMethod(object):
    def __init__(self, fnc, callback=None):
        self.Callable = fnc
        self.Callback = callback

    def __call__(self, *args, **kwargs):
        return AsyncCall(self.Callable, self.Callback)(*args, **kwargs)

def Async(fnc = None, callback = None):
    if fnc == None:
        def AddAsyncCallback(fnc):
            return AsyncMethod(fnc, callback)
        return AddAsyncCallback
        return AsyncMethod(fnc, callback)

And works exactly as requested:

def fnc():
Answered By: Nevyn

You can implement a decorator to make your functions asynchronous, though that’s a bit tricky. The multiprocessing module is full of little quirks and seemingly arbitrary restrictions – all the more reason to encapsulate it behind a friendly interface, though.

from inspect import getmodule
from multiprocessing import Pool

def async(decorated):
    r'''Wraps a top-level function around an asynchronous dispatcher.

        when the decorated function is called, a task is submitted to a
        process pool, and a future object is returned, providing access to an
        eventual return value.

        The future object has a blocking get() method to access the task
        result: it will return immediately if the job is already done, or block
        until it completes.

        This decorator won't work on methods, due to limitations in Python's
        pickling machinery (in principle methods could be made pickleable, but
        good luck on that).
    # Keeps the original function visible from the module global namespace,
    # under a name consistent to its __name__ attribute. This is necessary for
    # the multiprocessing pickling machinery to work properly.
    module = getmodule(decorated)
    decorated.__name__ += '_original'
    setattr(module, decorated.__name__, decorated)

    def send(*args, **opts):
        return async.pool.apply_async(decorated, args, opts)

    return send

The code below illustrates usage of the decorator:

def printsum(uid, values):
    summed = 0
    for value in values:
        summed += value

    print("Worker %i: sum value is %i" % (uid, summed))

    return (uid, summed)

if __name__ == '__main__':
    from random import sample

    # The process pool must be created inside __main__.
    async.pool = Pool(4)

    p = range(0, 1000)
    results = []
    for i in range(4):
        result = printsum(i, sample(p, 100))

    for result in results:
        print("Worker %i: sum value is %i" % result.get())

In a real-world case I would ellaborate a bit more on the decorator, providing some way to turn it off for debugging (while keeping the future interface in place), or maybe a facility for dealing with exceptions; but I think this demonstrates the principle well enough.

Answered By: xperroni


import threading, time

def f():
    print "f started"
    print "f finished"

Answered By: Antigluk

You could use eventlet. It lets you write what appears to be synchronous code, but have it operate asynchronously over the network.

Here’s an example of a super minimal crawler:

urls = ["",

import eventlet
from import urllib2

def fetch(url):

  return urllib2.urlopen(url).read()

pool = eventlet.GreenPool()

for body in pool.imap(fetch, urls):
  print "got body", len(body)
Answered By: Raj

Something like this works for me, you can then call the function, and it will dispatch itself onto a new thread.

from thread import start_new_thread

def dowork(asynchronous=True):
    if asynchronous:
        args = (False)
        start_new_thread(dowork,args) #Call itself on a new thread.
        while True:
            #do something...
            time.sleep(60) #sleep for a minute
Answered By: Nicholas Hamilton

As of Python 3.5, you can use enhanced generators for async functions.

import asyncio
import datetime

Enhanced generator syntax:

def display_date(loop):
    end_time = loop.time() + 5.0
    while True:
        if (loop.time() + 1.0) >= end_time:
        yield from asyncio.sleep(1)

loop = asyncio.get_event_loop()
# Blocking call which returns when the display_date() coroutine is done

New async/await syntax:

async def display_date(loop):
    end_time = loop.time() + 5.0
    while True:
        if (loop.time() + 1.0) >= end_time:
        await asyncio.sleep(1)

loop = asyncio.get_event_loop()
# Blocking call which returns when the display_date() coroutine is done
Answered By: camabeh

You can use concurrent.futures (added in Python 3.2).

import time
from concurrent.futures import ThreadPoolExecutor

def long_computation(duration):
    for x in range(0, duration):
    return duration * 2

print('Use polling')
with ThreadPoolExecutor(max_workers=1) as executor:
    future = executor.submit(long_computation, 5)
    while not future.done():


print('Use callback')
executor = ThreadPoolExecutor(max_workers=1)
future = executor.submit(long_computation, 5)
future.add_done_callback(lambda f: print(f.result()))

print('waiting for callback')

executor.shutdown(False)  # non-blocking

print('shutdown invoked')
Answered By: Big Pumpkin

You can use process. If you want to run it forever use while (like networking) in you function:

from multiprocessing import Process
def foo():
    while 1:
        # Do something

p = Process(target = foo)

if you just want to run it one time, do like that:

from multiprocessing import Process
def foo():
    # Do something

p = Process(target = foo)
Answered By: Keivan

The native Python way for asynchronous calls in 2021 with Python 3.9 suitable also for Jupyter / Ipython Kernel

Camabeh’s answer is the way to go since Python 3.3.

async def display_date(loop):
    end_time = loop.time() + 5.0
    while True:
        if (loop.time() + 1.0) >= end_time:
        await asyncio.sleep(1)

loop = asyncio.get_event_loop()
# Blocking call which returns when the display_date() coroutine is done

This will work in Jupyter Notebook / Jupyter Lab but throw an error:

RuntimeError: This event loop is already running

Due to Ipython’s usage of event loops we need something called nested asynchronous loops which is not yet implemented in Python. Luckily there is nest_asyncio to deal with the issue. All you need to do is:

!pip install nest_asyncio # use ! within Jupyter Notebook, else pip install in shell
import nest_asyncio

(Based on this thread)

Only when you call loop.close() it throws another error as it probably refers to Ipython’s main loop.

RuntimeError: Cannot close a running event loop

I’ll update this answer as soon as someone answered to this github issue.

Answered By: do-me

The newer asyncio running method in Python 3.7 and later is using instead of creating loop and calling loop.run_until_complete() as well as closing it:

import asyncio
import datetime

async def display_date(delay):
    loop = asyncio.get_running_loop()
    end_time = loop.time() + delay
    while True:
        await asyncio.sleep(1)
        if loop.time() > end_time:
Answered By: Benyamin Jafari