Как я могу создать зависимости между несколькими асин c методами в Python 3? - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть класс, который содержит несколько asyin c методов, и я хочу создать зависимости между ними. График зависимостей На этой картинке и биение, и окрестность зависят от радио, а суб зависит от окрестности, то есть после запуска радио я хочу запустить биение и окрестность. И после запуска соседей_чека я хочу запустить саб. У меня также есть функция asyinc_start, которая запускает методы, поэтому здесь я хочу управлять ими, но не могу.

Дайте мне несколько советов.

Код check_dependency.py выглядит следующим образом:

import asyncio
import sys
import os
from util import run`enter code here`
class ChkDependency():
    async def radio(self):
        print("Radio is initialized")
        await asyncio.sleep(2)


    async def pub(self):
        await asyncio.sleep(2)
        print("pub is initialized")


    async def heartbeat(self):
        print("heartbeat started")
        await asyncio.sleep(2)


    async def neigh_hood_check(self):
        await asyncio.sleep(2)
        print("checking for matches in neigh list")


    async def subs(self):
        await asyncio.sleep(2)
        print("match found")
        await asyncio.sleep(2)
        print("subscribing.....")


if __name__ == '__main__':
    chkdependency = ChkDependency()
    async def start():
        while True:
            await asyncio.wait([
                chkdependency.radio(),
                chkdependency.pub(),
                chkdependency.heartbeat(),
                chkdependency.neigh_hood_check(),
                chkdependency.subs(),
            ])    

    try:
        run(
            start(),
          )
    except KeyboardInterrupt:
        print("Exiting...")
        exit()

Код util.py выглядит следующим образом:

import asyncio

def run(*args):
    loop = asyncio.get_event_loop()
    loop.run_until_complete(asyncio.gather(*args))

Я думал о реализации зависимости с помощью семафора, но положительных результатов не было. Пожалуйста, помогите !!

1 Ответ

0 голосов
/ 08 апреля 2020

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

  1. Если вы просто хотите, чтобы методы выполнялись в заданный порядок, тогда просто сделайте это:

    try:
        while True:
            await chkdependency.radio()
            await chkdependency.pub()
            await chkdependency.heartbeat()
            await chkdependency.neigh_hood_check()
            await chkdependency.subs()
    

    Но в этом случае каждый последующий метод будет ожидать завершения предыдущего!

  2. Если вы хотите методы, которые должны гарантированно начинаться в указанном порядке и заканчиваться в любом порядке, незаменимы примитивы синхронизации:

    import asyncio
    from random import randint
    
    
    class ChkDependency:
        def __init__(self):
            self.radio_started = asyncio.Event()
            self.pub_started = asyncio.Event()
            self.heartbeat_started = asyncio.Event()
            self.neigh_hood_check_started = asyncio.Event()
            self.sub_started = asyncio.Event()
    
        async def radio(self):
            await self.radio_started.wait()
            print("1 Start radio")
            self.pub_started.set()
            await asyncio.sleep(randint(1, 5))
            print("1 Finish radio")
            self.radio_started.clear()
    
        async def pub(self):
            await self.pub_started.wait()
            print("2 Start pub")
            self.heartbeat_started.set()
            await asyncio.sleep(randint(1, 5))
            print("2 Finish pub")
            self.pub_started.clear()
    
        async def heartbeat(self):
            await self.heartbeat_started.wait()
            print("3 Start heartbeat")
            self.neigh_hood_check_started.set()
            await asyncio.sleep(randint(1, 5))
            print("3 Finish heartbeat")
            self.heartbeat_started.clear()
    
        async def neigh_hood_check(self):
            await self.neigh_hood_check_started.wait()
            print("4 Start neigh_hood_check")
            self.sub_started.set()
            await asyncio.sleep(randint(1, 5))
            print("4 Finish neigh_hood_check")
            self.neigh_hood_check_started.clear()
    
        async def subs(self):
            await self.sub_started.wait()
            print("5 Start subs")
            await asyncio.sleep(randint(1, 5))
            print("5 Finish subs")
            self.sub_started.clear()
    
        async def start(self):
            while True:
                self.radio_started.set()
                print("\nStart new cycle:")
                await asyncio.gather(
                    self.radio(),
                    self.pub(),
                    self.heartbeat(),
                    self.neigh_hood_check(),
                    self.subs()
                )
    
    
    async def main():
        chkdependency = ChkDependency()
        await chkdependency.start()
    
    if __name__ == '__main__':
        try:
            asyncio.run(main())
        except KeyboardInterrupt:
            print("Exiting...")
    
  3. Имейте в виду, что если вы сделаете это (или то же самое с asyncio.wait вместо asyncio.gather):

    async def start():
        while True:
            await asyncio.gather(
                chkdependency.radio(),
                chkdependency.pub(),
                chkdependency.heartbeat(),
                chkdependency.neigh_hood_check(),
                chkdependency.subs()
            )
    

    может показаться, что методы запускаются по очереди. Это потому, что внутри, asyncio.gather и asyncio.wait запускают их в al oop. Однако имейте в виду, что это поведение не гарантируется! А это значит, что в любой момент, например, в новой версии библиотеки или по некоторым внутренним причинам методы могут запускаться в другом порядке.

  4. Также кажется, что вы не метод run не нужен, поскольку asyncio.run делает то же самое!

...