superpig
superpig

Reputation: 21

how can i use async/await to call Future obj in python3.6

I have doubts about Python's await and hava an example,it tries to use await to fetch results from the future obj.

import time
import asyncio
import time
import random
import threading

db = {
    "yzh": "pig",
    "zhh": "big pig"
}
loop = asyncio.get_event_loop()

def _get_redis(username, clb):
    def foo():    
        data = db[username]    
        time.sleep(0.1)
        print("start clb")
        clb(data)
    t1 = threading.Thread(target=foo)
    t1.start()


def get_redis(username):
    print("start get redis")
    myfuture = asyncio.Future()
    def clb(result):
        print("clb call")
        myfuture.set_result(result)

    _get_redis(username, clb)
    return myfuture

async def main():
    print("start main")
    data = await get_redis("yzh")
    print("data is {}".format(data))

loop.run_until_complete(asyncio.ensure_future(main()))
loop.close()

and i got output without future's result:

start main
start get redis
start clb
clb call

How should i use await to get the future's result?I tried many times. Thanks for your help.

Upvotes: 1

Views: 461

Answers (1)

Vincent
Vincent

Reputation: 13423

As you said in your comment, you're supposed to use loop.call_soon_threadsafe when running an asyncio callback from a thread:

loop.call_soon_threadsafe(myfuture.set_result, result)

However, a better approach for calling a synchronous function from asyncio is to use loop.run_in_executor:

def _get_redis(username):
    time.sleep(0.1)
    return db[username]

async def get_redis(username):
    return await loop.run_in_executor(None, _get_redis, username)

This way, you won't have to deal with futures and thread-safe callbacks.

Upvotes: 1

Related Questions