Почему мне нужно отменить задачи в этом примере очереди? - PullRequest
1 голос
/ 12 июня 2019

Ну, я изучаю документацию по python для изучения моей работы. Я новичок в Python, а также в программировании. Я также не очень хорошо понимаю такие концепции программирования, как асинхронные операции.

Я использую Fedora 29 с Python 3.7.3 для примеров попытки очереди и lib asyncio.

Следуйте примеру операций очереди и асинхронности ниже:

import asyncio
import random
import time


async def worker(name, queue):
    while True:
        # Get a "work item" out of the queue.
        sleep_for = await queue.get()

        # Sleep for the "sleep_for" seconds.
        await asyncio.sleep(sleep_for)

        # Notify the queue that the "work item" has been processed.
        queue.task_done()

        print(f'{name} has slept for {sleep_for:.2f} seconds')


async def main():
    # Create a queue that we will use to store our "workload".
    queue = asyncio.Queue()

    # Generate random timings and put them into the queue.
    total_sleep_time = 0
    for _ in range(20):
        sleep_for = random.uniform(0.05, 1.0)
        total_sleep_time += sleep_for
        queue.put_nowait(sleep_for)

    # Create three worker tasks to process the queue concurrently.
    tasks = []
    for i in range(3):
        task = asyncio.create_task(worker(f'worker-{i}', queue))
        tasks.append(task)

    # Wait until the queue is fully processed.
    started_at = time.monotonic()
    await queue.join()
    total_slept_for = time.monotonic() - started_at

    # Cancel our worker tasks.
    for task in tasks:
        task.cancel()
    # Wait until all worker tasks are cancelled.
    await asyncio.gather(*tasks, return_exceptions=True)

    print('====')
    print(f'3 workers slept in parallel for {total_slept_for:.2f} seconds')
    print(f'total expected sleep time: {total_sleep_time:.2f} seconds')

asyncio.run(main())

Почему в этом примере мне нужно отменить задания? Почему я могу исключить эту часть кода

# Cancel our worker tasks.
    for task in tasks:
        task.cancel()
    # Wait until all worker tasks are cancelled.
    await asyncio.gather(*tasks, return_exceptions=True)

а пример нормально работает?

1 Ответ

0 голосов
/ 13 июня 2019

Почему в этом примере мне нужно отменить задачи?

Потому что в противном случае они будут зависать бесконечно, ожидая нового элемента в очереди, который никогда не прибудет.В этом конкретном примере вы все равно выходите из цикла событий, так что нет никакого вреда от их «зависания», но если бы вы сделали это как часть служебной функции, вы бы создали утечку сопрограммы.

Другими словамиотмена рабочих говорит им выйти, потому что их услуги больше не нужны и необходимы для освобождения связанных с ними ресурсов.

...