Я ожидаю, что оператор yield заставит функцию «выдавать контекст exeuction» (что бы это ни значило в Twisted) и позволил другому отложенному исполнить выполнение.
От ваши наблюдения, я так понимаю, вы уже разочаровались в этом ожидании. Чтобы быть совершенно ясным, это не то, что yield
делает в функции генератора, украшенной inlineCallbacks
.
То, что yield
делает в такой функции, это передает значение батуту. Если значение является Отложенным, батут приостанавливает работу генератора, пока Отложенный не сработает. Если значение не является отложенным, или когда отложенное срабатывает со значением, генератор возобновляет работу с отправленным ему значением.
Итак, поскольку yield
совпадает с yield None
и None
- это не Deferred
, эти yield
выражения - просто дорогой способ сказать None
.
Это также дает вам некоторое представление о том, как добиться того, о чем вы говорите. Чтобы приостановить выполнение, выдайте Deferred
, который не запускается до тех пор, пока вы не захотите возобновить выполнение.
Как правильно реализовать совместную многозадачность в Twisted и разрешить контекст выполнения go другому отложенному в строке?
Есть много возможных правильных способов сделать это. Особенности зависят в большей степени от ваших конкретных c требований к приложениям.
К сожалению, есть несколько легко объяснимых глупых ответов, которые могут показаться правильными, но, вероятно, в конечном итоге приведут к снижению производительности и затратному обслуживанию. Например, вы можете приостановить «итерацию реактора» (если такая вещь существует, что может быть меньше, чем вы думаете). Для этого выведите twisted.internet.task.deferLater(reactor, 0.0, lambda: None)
. Это выражение создает Deferred
, которое срабатывает не раньше, чем «ноль секунд» с этого момента, но также с ограничением, что оно не срабатывает вправо сейчас.
Однако, это позволяет всему Реализация реактора имеет шанс выполнить работу до возобновления работы вашего генератора, даже если нет никакой другой работы. Таким образом, вы платите большую стоимость процессора за возможность сотрудничества. Кроме того, это затрудняет тестирование функции путем введения взаимодействий по расписанию.
Альтернатива, которую Twisted предлагает попытаться справиться с некоторыми из этих трудностей, - это twisted.internet.task.cooperate
, что понижает inlineCallbacks
в пользу голого генераторы. Они действительно используют yield
, чтобы предложить точки приостановки, но делают это таким образом, чтобы не дать всему реактору шанса запуститься, прежде чем возобновить работу. Это решает некоторые проблемы с процессором и, возможно, некоторые трудности с обслуживанием, хотя в конечном итоге оно все еще вводит некоторые временные зависимости. Однако, по крайней мере, возможно работать на чистых генераторах без , включая cooperate
, что в некоторой степени уменьшает эту трудность (сравните это с inlineCallbacks
, где идиоматически написанный код разрушает базовый генератор и предлагает только функция, которая возвращает Deferred
для тестирования).