To try to answer your question I've modified one of the example from the asyncio docs to include more of what you are asking for. https://docs.python.org/3/library/asyncio-task.html
import asyncio
result2 = 0
async def compute(x, y):
print("Compute %s + %s ..." % (x, y))
await asyncio.sleep(1.0)
result2 = x*y
return x + y
async def print_sum(x, y):
result = await compute(x, y)
print("%s + %s = %s" % (x, y, result))
async def dosomethingelse():
print("I've got a lovely bunch of coconuts")
loop = asyncio.get_event_loop()
tasks = [print_sum(1, 2),
dosomethingelse(),
compute(2, 4)
]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
print(result2)
If you run the above you should see that dosomethingelse runs, while compute is waiting.
I found asynchronous programming really hard to wrap my mind around. But I think that asyncio is actually much more straightforward than threading or multiprocessing because everything runs in the same memory space and (with simple coroutines like this) the program flow is completely sequential. The first task runs until it hits an await, then the next task gets a chance, and so on. I highly recommend reading through the module documentation, which is quite good and trying to write some examples to explore each topic. Start with coroutines, then chaining, and then callbacks.
EDIT: I'll leave this here as I think it's a good simple example. Comment if you disagree. Note that the yield from syntax is because I was using a slightly older version of python 3 at the time.
I don't remember what tutorial I was reading but here is one of the first asyncio tests I wrote.
import asyncio
@asyncio.coroutine
def my_coroutine(task_name, seconds_to_sleep=3):
print("{0} sleeping for: {1} seconds".format(task_name, seconds_to_sleep))
yield from asyncio.sleep(seconds_to_sleep)
print("{0} is finished".format(task_name))
loop = asyncio.get_event_loop()
tasks = [my_coroutine("task1", 4),
my_coroutine("task2", 2),
my_coroutine("task3", 10)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()