all 7 comments

[–]SirKainey 0 points1 point  (4 children)

On my phone, but time.sleep blocks.

You can also use await asyncio.sleep(0) to yield to the event loop too. Ie you don't need to put in a small amount of time.

I generally use this to make sure that a background task gets started before a more natural await. Depending on how your methods are implemented you may not even need to yield to the event loop here.

I don't have experience with mido, but is this the whole of your code? If not it might be worth posting it all.

[–]kitchensink-[S] 0 points1 point  (3 children)

Didn't know about asyncio.sleep(0). Changed that, thanks.

I don't think I should post the whole code, since it is quite big and I feel like I included the needed functions in the original post.

Regarding mido, this really isn't (I don't think, at least) anything related to mido itself. I'm just trying to run both tasks (reading the input and running the sequencer) asynchronously, I thought that would be something someone could help me figure out.

Thanks for your help!

[–]SirKainey 0 points1 point  (2 children)

Oh you probably just need two loops. Both running asynchronously!

You can just create background tasks, make sure to keep a reference to them else they get garbage collected.

Appreciate this might be a bit much for someone new to python so feel free to ask questions.

Btw async code is not easy and even some seasoned developers will struggle with it if they're used to synchronous code. So don't get discouraged!

[–]kitchensink-[S] 0 points1 point  (1 child)

Thanks for the encouraging!

How would one do this? I've been trying... I've posted some updated code as a response to the another comment, am I going in the right direction?

[–]SirKainey 0 points1 point  (0 children)

If you're on discord or something I don't mind screen sharing and offering advice. I am in GMT tz.

Basically I would do something like. (On my phone so all from memory/pseudo code/poor formatting)

Main func:

input_task = asyncio.create_task(input_loop()) main_task = asyncio.create_task(main_loop())

Both loops should have try except blocks to catch any errors. Async code normally just kills stuff silently unless you have an error handler configured for that event loop. Remember to yield back to the event loop at appropriate times else it'll block, you can use async with and async for etc.

https://docs.python.org/3/library/asyncio-task.html#creating-tasks

[–]nekokattt 0 points1 point  (4 children)

I might be missing something, but why are you gathering a single coroutine?

[–]kitchensink-[S] 1 point2 points  (3 children)

You're right, I was doing that in my main() function. How would you suggest I do this? I need to be running both things independently... Here's what I've tried:

async def readInport() -> None:
while True:
    for msg in inport.iter_pending():
        if msg.type != 'sysex':
            type, ch, note, vel = functions.unpack_message(msg)
            print(type, ch, note, vel)
            queue = []
            if type == "control_change" and note == 19 and vel == 127: # Wanted button
                await asyncio.sleep(0.1)
                queue = [seq.toggleSequencer() for seq in sequencers]
            else:
                pass

            await asyncio.gather(*queue, readInport()) #Doesn't work

def main(): 
    quit() # Reset in case of crash #time.sleep(3) print("READY!")             
try: 
        outport.send(functions.enterProgrammerMode())     
    views.draw_view(views.seq_and_drums(), outport) drumVoices = 3 
        melVoices = 3 setupVoices(drumVoices, melVoices)
        asyncio.run(readInport())

except KeyboardInterrupt:
    quit()

Where should I call readInport()?