Как сжать код, который выбирает, сколько параллельных задач выполняется на основе ввода? - PullRequest
2 голосов
/ 12 апреля 2019

У меня есть проект scrapper, который работает с асинхронными запросами, запрашивает библиотеку и трио. Я хотел бы выбрать, сколько параллельных задач выполняется на основе ввода, но мой код длинный и примитивный

Я использую объект нереста и питомника трио для одновременных задач (документы: https://trio.readthedocs.io/en/latest/reference-core.html)

Вот мой неаккуратный код:

import trio
import asks
Number_of_workers = input("how many workers do you want?: ") #How many tasks I want between 1 and 5

async def child1(s):
    r = await s.get("https://example.com", params={"example":"example"})
    print("do something with", r.text)

async def child2():
    r = await s.get("https://example.com", params={"example":"example"})
    print("do something with", r.text)

async def child3():
    r = await s.get("https://example.com", params={"example":"example"})
    print("do something with", r.text)

async def child4():
    r = await s.get("https://example.com", params={"example":"example"})
    print("do something with", r.text)

async def child5():
    r = await s.get("https://example.com", params={"example":"example"})
    print("do something with", r.text)

async def parent(): 
    s = Session(connections=5)
    async with trio.open_nursery() as nursery:
        if int(Number_of_workers) == 1:
            nursery.start_soon(child1, s)

        elif int(Number_of_workers) == 2:
            nursery.start_soon(child1, s)
            nursery.start_soon(child2, s)

        elif int(Number_of_workers) == 3:
            nursery.start_soon(child1, s)
            nursery.start_soon(child2, s)
            nursery.start_soon(child3, s)

        elif int(Number_of_workers) == 4:
            nursery.start_soon(child1, s)
            nursery.start_soon(child2, s)
            nursery.start_soon(child3, s)
            nursery.start_soon(child4, s)

        elif int(Number_of_workers) == 5:
            nursery.start_soon(child1, s)
            nursery.start_soon(child2, s)
            nursery.start_soon(child3, s)
            nursery.start_soon(child4, s)
            nursery.start_soon(child5, s)
trio.run(parent)

Я думаю, вы понимаете, к чему я клоню, этот пример кода теоретически работает, но он очень длинный для чего-то, что может быть сокращено до меньшего количества строк кода.

Этот вид схемы становится особенно длинным при работе с 10 или 20 работниками и всегда ограничен заранее определенной суммой.

Внутри себя каждый дочерний элемент - это один и тот же код, он просто получает разные данные (например, params и url) из файла .py внешнего модуля с помощью importlib.

Есть ли способ сократить это до более оптимизированного кода?

1 Ответ

1 голос
/ 13 апреля 2019

Вы можете использовать цикл!

async def child(s):
    r = await s.get("https://example.com", params={"example":"example"})
    print("do something with", r.text)

async def parent(): 
    s = Session(connections=5)
    async with trio.open_nursery() as nursery:
        for i in range(Number_of_workers):
            nursery.start_soon(child, s)

Редактировать: вот отдельная демонстрация, которую вы можете запустить, чтобы убедить себя, что на самом деле она запускает параллельные задачи. Также демонстрируется, как вы можете передавать разные значения параметров в разные задачи, чтобы они выполняли разные задачи - в этом случае выведите разные сообщения:

import trio

Number_of_workers = 10

async def child(i):
    print("child {}: started".format(i))
    await trio.sleep(5)
    print("child {}: finished".format(i))

async def parent():
    async with trio.open_nursery() as nursery:
        for i in range(Number_of_workers):
            nursery.start_soon(child, i)

trio.run(parent)

Попробуйте и посмотрите!

...