簡體   English   中英

如何從使用Tornado的IOLoop運行的協程返回值?

[英]How to return a value from a coroutine that was run with Tornado's IOLoop?

假設我有這個異步函數(Python 3.5)

async def func():
    return '42'

我有一個Tornado I / O循環,正在尋找一種執行它的方法。

import tornado.ioloop

ioloop = tornado.ioloop.IOLoop.current()
ioloop.start()

我可以只使用IOLoop.add_callback(func) ,但我也需要一個返回值。
關於從中獲取返回值需要什么的任何想法?

編輯
func coroutine方法實際上接收一個字符串,並將其發送到服務器,接收響應,對其進行適當的解包並返回一個數據元組。
從常規(非異步)方法中調用該方法,該方法根據其參數組裝字符串,並應該獲得響應並將數據返回給調用方。
IO循環是一個類變量(可通過self.訪問self.

這是一個例子:

def register(self, arg1, arg2):
    # process args here

    ret_value = self.ioloop.add_callback(func, arg1, arg2)  
    # The above line is incorrect code, just for the idea

    return ret_value

第二編輯
這是引發AssertionError的代碼部分:

async def _send(self, arg1):
    self.ws.write_message(arg1)
    resp = await self.ws.read_message()
    return resp

def callback(self, future):
    print('future', future.result())

def register(self, arg1):
    future = self._send(arg1)
    self.ioloop.add_future(future, self.callback)

我使用__init__類中的PeriodicCallback開始執行register
register方法中的變量future包含<coroutine object Client._send at 0xb652c41c>並且只有在is_future給出的是concurrent.futures.Future tornado.concurrent.Futuretornado.concurrent.Future的實例時, is_future檢查才會通過

兩種選擇:使register協程,或在回調中接收func的返回值。

選項一:

async def register(self, arg1, arg2):
    ret_value = await func(arg1, arg2)
    return ret_value

選項二:

def callback(future):
    try:
        ret_value = future.result()
        # Do something with ret_value here.
    except Exception as exc:
        # Log the exception or something.
        print(exc)

def register(self, arg1, arg2):
    future = func(arg1, arg2)
    self.ioloop.add_future(future, callback)

顯然,選項二很尷尬,因為您不能在原始register函數中使用ret_value。 我會選擇一種, register一個協程。 然后, register調用者必須一直是協程,一直到調用堆棧。

那是異步編程的一個鐵律:為了通過網絡進行通信,您的函數必須是執行yieldawait的協程,或者您必須注冊一個回調並退出當前函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM