2016-11-08 8 views
1

Недавно был добавлен метод add_done_callback к распределенному объекту Future, который позволяет вам предпринять какие-то действия после окончания будущего, независимо от того, удалось это или нет.Как получить результат будущего в обратном вызове?

http://distributed.readthedocs.io/en/latest/api.html?highlight=add_done_callback#distributed.client.Future.add_done_callback

Функция обратного вызова будет висеть, если вы пытаетесь напрямую вызвать любого из методов result, exception или traceback на пройденном будущем объекте.

исключения и TRACEBACK однако может быть доступен в функции обратного вызова следующим образом: fut._exception().result() fut._traceback().result()

Стараясь по той же схеме с результатом - т.е. fut._result().result() вызывает исключение:

File "C:\Python\lib\site-packages\tornado\concurrent.py", line 316, in _check_done 
    raise Exception("DummyFuture does not support blocking for results") 
Exception: DummyFuture does not support blocking for results 

Не имея возможности чтобы получить доступ к результату будущего в обратном вызове, возможность добавления обратного вызова для меня ограничена.

Я что-то упустил - is Есть ли способ получить результат будущего в обратном вызове?

В документации asyncio это, кажется, привести пример, когда доступ к методу result непосредственно можно:

https://docs.python.org/3/library/asyncio-task.html#example-future-with-run-forever

... Я не знаю, как это связано с торнадо/распространяться, но было бы очень полезно иметь возможность сделать то же самое.

from distributed import Client 


client = Client("127.0.0.1:8786") 

def f(delay): 
    from time import sleep 
    from numpy.random import randn 
    sleep(delay) 
    if randn() > 1: 
     1/0 
    return delay 

def callback(fut): 
    import logging 
    logger = logging.getLogger('distributed') 
    if fut.status == 'finished': 
     res = future._result().result() # <-------------- Doesn't work! 
     logger.info("{!r} - {!s}".format(fut, res)) 
    else: 
     logger.info("{!r} - {!s}".format(fut, fut.status)) 


args = rand(10) 
futs = client.map(f, args) 
for fut in futs: 
    fut.add_done_callback(callback) 

ответ

1

В настоящее время ваш обратный вызов вызывается в цикле событий Tornado. Если вы хотите получить результат в будущем, вам придется использовать API Tornado.

Вот минимальный пример:

In [1]: from distributed import Client 
In [2]: client = Client() 
In [3]: def inc(x): 
    ...:  return x + 1 
    ...: 
In [4]: from tornado import gen 

In [5]: @gen.coroutine 
    ...: def callback(future): 
    ...:  result = yield future._result() 
    ...:  print(result * 10) 
    ...:  
In [6]: future = client.submit(inc, 1) 

In [7]: future.add_done_callback(callback) 

20 

Однако ваш вопрос подчеркивает, что, возможно, это не самый интуитивный способ для пользователей, чтобы взаимодействовать с add_done_callback, так что я не удивлюсь, если мы ввели ломку изменить для более поздних версий.

In [8]: import distributed 

In [8]: distributed.__version__ 
Out[8]: '1.14.0' 

 Смежные вопросы

  • Нет связанных вопросов^_^