Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
131 views
in Technique[技术] by (71.8m points)

How to multiprocess async/await functions in python?

I need to run an event every 60 seconds to all my cars. My problem with the code below is the while loop doesn't end until the timeout (60) does and hence only the first car in cars is run.

class RunCars(BaseEvent):

    def __init__(self):
        interval_seconds = 60  # Set the interval for this event
        super().__init__(interval_seconds)

    # run() method will be called once every {interval_seconds} minutes
    async def run(self, client, cars):
        for car in cars:        
            channel = get_channel(client, "general")
            await client.send_message(channel, 'Running this '+str(car))
            await msg.add_reaction(str(get_emoji(':smiley:'))) 
            
            reaction = None
            while True:
                if str(reaction) == str(get_emoji(':smiley:'))
                    await client.send_message(channel, 'Finished with this '+str(car))
                try:
                    reaction, user = await client.wait_for('reaction_add', timeout=60, check=check)
                except:
                    break

I tried changing the code into a multithreaded process but had trouble with async/await inside the function and problems with pickling the function itself.

I'd appreciate any suggestions for how to go about this..


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The asyncio module lets you execute multiple async method concurrently using the gather method. I think you can achieve the behavior you want by defining a method that runs a single car, and then replacing your for-loop with a call to gather, which will execute multiple run_one coroutines (methods) concurrently:

import asyncio

class RunCars(BaseEvent):

    def __init__(self):
        interval_seconds = 60  # Set the interval for this event
        super().__init__(interval_seconds)


    async def run(self, client, cars):
        coroutines = [self.run_one(client, car) for car in cars]
        asyncio.gather(*coroutines)

    async def run_one(self, client, car):
        channel = get_channel(client, "general")
        await client.send_message(channel, 'Running this '+str(car))
        await msg.add_reaction(str(get_emoji(':smiley:'))) 
          
        reaction = None
        while True:
            if str(reaction) == str(get_emoji(':smiley:'))
                await client.send_message(channel, 'Finished with this '+str(car))
            try:
                reaction, user = await client.wait_for('reaction_add', timeout=60, check=check)
            except:
                break

In general, when writing async code, you should try to replace sequential calls to async methods - basically for-loops that call async methods - with gather statements so they execute concurrently.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...