У меня есть функция defer.inlineCallback
для постепенного обновления большого (> 1k) списка за один раз. Этот список может измениться в любое время, и я получаю ошибки из-за этого поведения.Петля через изменяющийся набор данных с inlineCallbacks/yield (python-twisted)
Самое простое представление о том, что я делаю это: -
@defer.inlineCallbacks
def _get_details(self, dt=None):
data = self.data
for e in data:
if needs_update(e):
more_detail = yield get_more_detail(e)
do_the_update(e, more_detail)
schedule_future(self._get_details)
self.data
список словарей, который первоначально заполняется основной информацией (например, имя и ID) при запуске приложения. _get_details
будет запускаться всякий раз, когда разрешается реактором, чтобы получить более подробную информацию по каждому элементу данных, обновив элемент по мере его продвижения.
Это хорошо работает, когда self.data
не изменяется, но после его изменения (может быть в любой точке) цикл, очевидно, ссылается на неверную информацию. Фактически в этой ситуации было бы лучше просто полностью остановить цикл.
Я могу установить флаг в моем классе (который inlineCallback
может проверить) при изменении данных.
- Куда должна проводиться эта проверка?
- Как выполняется код
inlineCallback
по сравнению с обычнымdeferred
(и даже с обычным генератором питона). - Выполняется ли выполнение кода каждый раз, когда он встречает
yield
(т. Е. Могу ли я полагаться на этот код между однимyield
и рядом с атомарным)? - В случае ненадежных больших списков, должен ли я даже перебирать данные (
for e in data
), или есть лучший способ?
Спасибо, это мой вывод. Что касается случая использования, мое приложение управляется событиями, но поскольку обновление является длительным, очень делимым и основано на относительно волатильных данных, я прибегаю к решению, основанному на большинстве усилий, которое просто пытается обновить все, что нуждается в обновлении, а затем позволит продолжить работу реактора. Предыдущие попытки «обновления в фоновом режиме» на основе потоков были еще хуже, так как обновление почти гарантировалось, что оно будет неправым к моменту его завершения (для моих текущих обновлений набора данных требуется 20-30 секунд). –