0

I have a problem at work where I have to wait for 10 seconds when InstrInstallSucceeded event comes in, without blocking the main thread, I should wait for InstrInstallFailed to appear, so in other words 'ToolOn', 'ToolOn', 'ToolOn' should appear without any wait.

import asyncio
from threading import Thread
import time
FLAG = True



async def sleep_loop(t, event):
    global FLAG
    print(event)
    if event == 'InstrInstallSucceeded':
        # spwan a seperate thread here such that 
        # toolon events are not blocked by the sleep
        await asyncio.sleep(t)
        FLAG = True
    if event == 'InstrInstallFailed':
        # and I want to update the FLAG whenever I see event == 'InstrInstallFailed'
        FLAG = False



async def keep_print():
    print(f'Beginning FLAG:: {FLAG}')
    while FLAG:
        pass
    print(f'End FLAG:: {FLAG}')



def start_loop(loop, t):
    print("in start loop")
    asyncio.set_event_loop(loop)
    for i in ['InstrInstallSucceeded', 'ToolOn','ToolOn', 'ToolOn', 'InstrInstallFailed']:
        loop.run_until_complete(asyncio.sleep(1))
        loop.run_until_complete(sleep_loop(t, i))

loop = asyncio.get_event_loop()
new_loop = asyncio.new_event_loop()
t = Thread(target=start_loop, args=(new_loop,10))
t.start()
coro = keep_print()
loop.run_until_complete(coro)

output

in start loop
Beginning FLAG:: True
Executing <Task pending coro=<sleep() running at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/tasks.py:482> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x1043f2be8>()] created at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py:284> cb=[_run_until_complete_cb() at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py:185] created at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py:452> took 0.118 seconds
InstrInstallSucceeded
ToolOn
ToolOn
ToolOn
InstrInstallFailed
End FLAG:: False
Executing <Task finished coro=<keep_print() done, defined at fut.py:21> result=None created at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py:452> took 15.756 seconds

EDIT: using python 3.6.7

import asyncio

async def dispatch_event(event, alert):
    print(event)
    if event == 'InstrInstallSucceeded':
        # spawn a coroutine if you need something done in parallel
        #asyncio.create_task(xxx())
        await asyncio.sleep(10)
    if event == 'InstrInstallFailed':
        await asyncio.sleep(.5)

    # alert the watcher(s) of the event that was dispatched
    alert.last_event = event
    alert.set()

async def keep_print(alert):
    while True:
        print(f'Beginning FLAG:: {alert.last_event}')
        await alert.wait()
        alert.clear()
        print(f'End FLAG:: {alert.last_event}')

async def main():
    alert = asyncio.Event()
    alert.last_event = None
    # spawn keep_print in the "background"
    loop = asyncio.get_event_loop()
    t = loop.create_task(keep_print(alert))
    for i in ['InstrInstallSucceeded', 'ToolOn','ToolOn', 'ToolOn', 'InstrInstallFailed']:
        await asyncio.sleep(1)
        await dispatch_event(i, alert)
    await asyncio.sleep(1)
    t.cancel()
loop = asyncio.get_event_loop()
loop.run_until_complete(main())

edit as suggested by @user418.....

async def dispatch_event(event,alert):

    alert.last_event = event
    alert.set()

    print(event)
    if event == 'InstrInstallSucceeded':
        # spawn a coroutine if you need something done in parallel
        #asyncio.create_task(xxx())
        await asyncio.sleep(10)
    if event == 'InstrInstallFailed':
        await asyncio.sleep(.5)
    # alert the watcher(s) of the event that was dispatched
1
  • I want to contend the downvote, I would like to know why my question was downvoted ? Commented Oct 7, 2019 at 1:54

1 Answer 1

1

Threads and asyncio don't go together, except in specific circumstances (e.g. the implementation of run_in_executor). Instead of spawning new threads, spawn new coroutines.

For example:

import asyncio

async def dispatch_event(event, alert):
    print(event)
    if event == 'InstrInstallSucceeded':
        # spawn a coroutine if you need something done in parallel
        #asyncio.create_task(xxx())
        await asyncio.sleep(1)
    if event == 'InstrInstallFailed':
        await asyncio.sleep(.5)

    # alert the watcher(s) of the event that was dispatched
    alert.last_event = event
    alert.set()

async def keep_print(alert):
    while True:
        print(f'Beginning FLAG:: {alert.last_event}')
        await alert.wait()
        alert.clear()
        print(f'End FLAG:: {alert.last_event}')

async def main():
    alert = asyncio.Event()
    alert.last_event = None
    # spawn keep_print in the "background"
    t = asyncio.create_task(keep_print(alert))
    for i in ['InstrInstallSucceeded', 'ToolOn','ToolOn', 'ToolOn', 'InstrInstallFailed']:
        await asyncio.sleep(1)
        await dispatch_event(i, alert)
    await asyncio.sleep(1)
    t.cancel()

asyncio.run(main())
Sign up to request clarification or add additional context in comments.

7 Comments

ok this does not work for me as I increased time to 10 seconds for await asyncio.sleep(10) in dispatch_event at condition if event == 'InstrInstallSucceeded': it seems to wait there for 10 seconds, and the continue. also I am using python 3.6.7 so I have to made certain modifications as well
ok so if I create a new event loop I am able to make the wait out in separate loop, but I have a new problem with my new code, which is over here pastebin.com/ade9mYSf TLDR; what I want to do is to set FLAG to False when the the time runs out in the new_event_loop
@VaibhavChauhan You can rather move the setting of the alert to the beginning of the dispatch_event(). Asyncio is single-threaded, you simply don't need a separate thread and event loop.
from what I understood I tried your suggestion as requested @user481....., it' in my edit, but that did not help me much. please take a look
@VaibhavChauhan Have you tried using asyncio.create_task() as indicated in the comment?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.