Ответ 1
Нет, совлокальные подпрограммы не связаны ни с какими потоками. Совлокальные подпрограммы допускают совместную многозадачность в том, что каждая совместная процедура дает контроль на добровольной основе. Нитки, с другой стороны, переключаются между единицами в произвольных точках.
До Python 3.4 можно было писать совлокальные подпрограммы с использованием генераторов; используя выражения yield
или yield from
в теле функции, вы создаете вместо этого объект-генератор, где код выполняется только тогда, когда вы перебираете генератор. Вместе с дополнительными библиотеками циклов событий (например, asyncio
) вы можете написать совлокальные подпрограммы, которые будут сигнализировать о цикле событий, что они будут заняты (ожидание I/O возможно), и что еще одна совместная процедура может быть запущена за это время:
import asyncio
import datetime
@asyncio.coroutine
def display_date(loop):
end_time = loop.time() + 5.0
while True:
print(datetime.datetime.now())
if (loop.time() + 1.0) >= end_time:
break
yield from asyncio.sleep(1)
Каждый раз, когда вышеприведенный код переходит к строке yield from asyncio.sleep(1)
, цикл событий может запускать другую совместную процедуру, потому что эта процедура не собирается делать ничего в течение следующей секунды.
Поскольку генераторы могут использоваться для всех видов задач, а не только для подпрограмм, а потому, что при написании подпрограммы с использованием синтаксиса генератора могут смущать новых пользователей, PEP вводит новый синтаксис, который делает более понятным, что вы написав совместную программу.
При реализации PEP вышеуказанный образец можно записать вместо:
async def display_date(loop):
end_time = loop.time() + 5.0
while True:
print(datetime.datetime.now())
if (loop.time() + 1.0) >= end_time:
break
await asyncio.sleep(1)
Результирующий объект coroutine
по-прежнему нуждается в цикле событий для управления совместными подпрограммами; цикл событий был бы await
для каждой совместной подпрограммы по очереди, которая будет выполнять те совлокальные подпрограммы, которые в настоящее время не выполняются await
для завершения чего-либо.
Преимущества в том, что с помощью встроенной поддержки вы также можете ввести дополнительный синтаксис для поддержки асинхронных менеджеров контекста и итераторов. Ввод и выход из диспетчера контекста или переключение на итератор затем могут стать больше точек в вашей совместной процедуре, которые сигнализируют, что другой код может работать вместо этого, потому что что-то ждет снова.