Форум сайта python.su
Есть две функции: одна долго работает с файловой системой, другая исполняет запрос к базе данных и в зависимости от результата, либо ничего не возвращает, либо бросает исключение. Нужно первую функцию запустить в отдельном потоке и паралельно с ней выполнить запрос к базе данных. Взависимости от результата обеих фукнций, нужно вызвать или 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()
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()
Офлайн
d1 = threads.deferToThread(execute_query, 'd1')
d2 = threads.deferToThread(work_with_filesystem, 'd2')
defer.DeferredList([d1, d2])\
.addCallback(callback)\
.addErrback(errback)
Офлайн
Ошибка:assert not isinstance(result, 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
Офлайн
Офлайн
Я знаю что есть документация. Цитата, которую я привел - с этой страницы. Если знаете почему работает не так как я думаю должно, скажите.
Офлайн
Для
d = some_func()
d.addCallback(callback1)
d.addCallback(callback2)
d.addCallback(callback3)
d.addErrback(errback1)
d.addErrback(errback2)
d.errback(123)
#d.callback(123)
Офлайн
Непонятна последняя строчка в документации, которую я привел.
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)
Отредактировано (Янв. 30, 2012 18:18:52)
Офлайн
svasЭтот код выводит результат:
callback2 и callback3 не вызывались
some func
errback1
callback2
callback3
Офлайн
Ну да. Так и должно быть.
Офлайн