Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 30, 2012 13:10:43

svas
От:
Зарегистрирован: 2010-01-27
Сообщения: 239
Репутация: +  9  -
Профиль   Отправить e-mail  

twisted, генерация Deferred

Есть две функции: одна долго работает с файловой системой, другая исполняет запрос к базе данных и в зависимости от результата, либо ничего не возвращает, либо бросает исключение. Нужно первую функцию запустить в отдельном потоке и паралельно с ней выполнить запрос к базе данных. Взависимости от результата обеих фукнций, нужно вызвать или callback (если обе функции завершились удачно) или errback (если хотя бы одна из функций завершилась неудачно). Как такое можно реализовать? Как по отдельности это сделать я знаю.

from twisted.internet import defer, reactor
from twisted.internet import threads
import time
import sys

def execute_query(param):
def _query_result_callback(res):
sys.stderr.write('query result callback. res - %s\n' % str(res))
return res

sys.stderr.write('executing query, param - %s\n' % (param))
d = defer.succeed(param)
d.addCallback(_query_result_callback)
return d

def work_with_filesystem(param):
raise Exception(param)
sys.stderr.write('work with fyle system, param - %s\n' % param)
time.sleep(1.0)
return param

def callback(param):
sys.stderr.write('callback, param - %s\n' % param)

def errback(f):
sys.stderr.write('errback, param - %s\n' % (str(f.value)))

d1 = execute_query('d1')
d1.addCallback(callback)
d1.addErrback(errback)

d2 = threads.deferToThread(work_with_filesystem, 'd2')
d2.addCallback(callback)
d2.addErrback(errback)

reactor.callLater(5, reactor.stop)
reactor.run()
Нужно как-то объединить deferreds d1 и d2
Так работает, но функции вызываются последовательно
from twisted.internet import defer, reactor
from twisted.internet import threads
import time
import sys

def execute_query(param):
def _query_result_callback(res):
sys.stderr.write('query result callback. res - %s\n' % str(res))
return res

sys.stderr.write('executing query, param - %s\n' % (param))
d = defer.succeed(param)
d.addCallback(_query_result_callback)
return d

def work_with_filesystem(param):

sys.stderr.write('work with fyle system, param - %s\n' % param)
time.sleep(1.0)
return param

def callback(param):
sys.stderr.write('callback, param - %s\n' % param)

def errback(f):
sys.stderr.write('errback, param - %s\n' % (str(f.value)))

d = threads.deferToThread(work_with_filesystem, 'qwe')
d.addCallback(execute_query)
d.addCallback(callback)
d.addErrback(errback)

reactor.callLater(5, reactor.stop)
reactor.run()



Офлайн

#2 Янв. 30, 2012 13:27:46

bw
От:
Зарегистрирован: 2007-09-26
Сообщения: 938
Репутация: +  20  -
Профиль   Адрес электронной почты  

twisted, генерация Deferred

d1 = threads.deferToThread(execute_query, 'd1')
d2 = threads.deferToThread(work_with_filesystem, 'd2')

defer.DeferredList([d1, d2])\
.addCallback(callback)\
.addErrback(errback)
..bw



Офлайн

#3 Янв. 30, 2012 14:19:10

svas
От:
Зарегистрирован: 2010-01-27
Сообщения: 239
Репутация: +  9  -
Профиль   Отправить e-mail  

twisted, генерация Deferred

Ошибка:assert not isinstance(result, Deferred).



Офлайн

#4 Янв. 30, 2012 15:56:06

svas
От:
Зарегистрирован: 2010-01-27
Сообщения: 239
Репутация: +  9  -
Профиль   Отправить e-mail  

twisted, генерация Deferred

Че-то не понимаю я эти Deferred
В документации сказано:

When the result is ready, give it to the Deferred object. .callback(result) if the operation succeeded, .errback(failure) if it failed. Note that failure is typically an instance of a
twisted.python.failure.Failure instance.

Deferred object triggers previously-added (call/err)back with the result or failure. Execution then follows the following rules, going down the chain of callbacks to be processed.

Result of the callback is always passed as the first argument to the next callback, creating a chain of processors.

If a callback raises an exception, switch to errback.

An unhandled failure gets passed down the line of errbacks, this creating an asynchronous analog to a series to a series of except: statements.

If an errback doesn't raise an exception or return a twisted.python.failure.Failure instance, switch to callback.
последнюю строчку я перевожу примерное так
Если errback не запускает исключение или возвращает экземпляр twisted.python.failure.Failure, переключаемся на callback
Как должен работать такой код? Как я понимаю, если первый errback не запускает исключение и не возвращает …Failure, то должны запускаться callback'и.
from twisted.internet import defer, reactor
from twisted.internet import threads
import time
import sys


def some_func():
sys.stderr.write('some func\n')
return defer.Deferred()

def callback1(*args):
sys.stderr.write('callback1\n')

def callback2(*args):
sys.stderr.write('callback2\n')

def callback3(*args):
sys.stderr.write('callback3\n')

def errback1(*args):
sys.stderr.write('errback1\n')

def errback2(*args):
sys.stderr.write('errback2\n')

d = some_func()
d.addCallback(callback1)
d.addCallback(callback2)
d.addCallback(callback3)

d.addErrback(errback1)
d.addErrback(errback2)

d.errback(123)
#d.callback(123)


reactor.callLater(5, reactor.stop)
reactor.run()
Выводится
some func
errback1
Если вызывать не errback а callback и в callback1 запустить исключение ничего не меняется. Что я не понимаю?



Офлайн

#5 Янв. 30, 2012 16:18:32

s0rg
От:
Зарегистрирован: 2011-06-05
Сообщения: 777
Репутация: +  25  -
Профиль   Отправить e-mail  

Офлайн

#6 Янв. 30, 2012 16:37:15

svas
От:
Зарегистрирован: 2010-01-27
Сообщения: 239
Репутация: +  9  -
Профиль   Отправить e-mail  

twisted, генерация Deferred

Я знаю что есть документация. Цитата, которую я привел - с этой страницы. Если знаете почему работает не так как я думаю должно, скажите.



Офлайн

#7 Янв. 30, 2012 17:25:41

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

twisted, генерация Deferred

Для

d = some_func()
d.addCallback(callback1)
d.addCallback(callback2)
d.addCallback(callback3)

d.addErrback(errback1)
d.addErrback(errback2)

d.errback(123)
#d.callback(123)
Поток будет:

c1 c2 c3 —————->
/
——————-> e2 e2

Что вам непонятно?



Офлайн

#8 Янв. 30, 2012 18:12:59

svas
От:
Зарегистрирован: 2010-01-27
Сообщения: 239
Репутация: +  9  -
Профиль   Отправить e-mail  

twisted, генерация Deferred

Непонятна последняя строчка в документации, которую я привел.

If an errback doesn't raise an exception or return a twisted.python.failure.Failure instance, switch to callback.
Как я ее перевел
Если errback не запускает исключение или возвращает экземпляр twisted.python.failure.Failure, переключаемся на callback
Я понимаю это так: вызывается первый errback, он не запускает исключение и не возвращает Failure, то должен запускаться callback2. Может я неправильно перевел?

Разобрался, спасибо
Почему-то не работал такой код
d = some_func()
d.addCallback(callback1)
d.addErrback(errback1)
d.addCallback(callback2)
d.addErrback(errback2)
d.addCallback(callback3)

d.errback(123)
callback2 и callback3 не вызывались



Отредактировано (Янв. 30, 2012 18:18:52)

Офлайн

#9 Янв. 31, 2012 07:27:28

agalen
От:
Зарегистрирован: 2011-03-23
Сообщения: 185
Репутация: +  17  -
Профиль   Отправить e-mail  

twisted, генерация Deferred

svas
callback2 и callback3 не вызывались
Этот код выводит результат:
some func
errback1
callback2
callback3



Офлайн

#10 Янв. 31, 2012 08:48:18

svas
От:
Зарегистрирован: 2010-01-27
Сообщения: 239
Репутация: +  9  -
Профиль   Отправить e-mail  

twisted, генерация Deferred

Ну да. Так и должно быть.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version