简体   繁体   English

Python如何使用asyncio使function同时运行

[英]Python How to make function run simultaneously using asyncio

I am currently new to Python and wanted to create a system that takes 10 customers that come in at an interval of 1 - 25 seconds.我目前是 Python 的新手,我想创建一个系统,让 10 位顾客每隔 1-25 秒进来一次。 They are sent to a queue, and the customers in front of the queue will be sent to one of the four open counters.他们被送到一个队列,队列前面的顾客将被送到四个开放柜台之一。 The counter will service them for 1-100 seconds and record each customer's start time and end time of service.柜台会为他们服务1-100秒,并记录每位顾客的服务开始时间和结束时间。 I wanted to run the customer entering and the counter service simultaneously using asyncio but am unable to make them run simultaneously as they run in order.我想使用 asyncio 同时运行客户进入和柜台服务,但无法让它们在按顺序运行时同时运行。 My question is, how can I make my code able to run these two functions simultaneously?我的问题是,如何让我的代码能够同时运行这两个功能? My code:我的代码:

import asyncio
from random import randint
import collections
import time
#create counter true false
Counter_List = {0: True, 1: True, 2: True, 3: True}
#hash table 
served = collections.defaultdict(list)
#empty que list
que_list = collections.deque([])
#global variable
total_customer = 0
counter = 0
start_time = time.time()
#event loop
#interarrival time
async def interarrival_time():
    global total_customer
    while total_customer < 10:
        print('customer ' + str(total_customer) + ' entered')
        time.sleep(randint(1,25))
        #que to right side
        que_list.append(total_customer)
        total_customer += 1
       
#service time          
#start service
async def service_start():
    global counter, total_customer, start_time
    while counter <= 4 and len(que_list) > 0:
        for x in Counter_List:
            if Counter_List[x] == True:
                #set to false the current counter
                Counter_List[x] = False
                counter += 1
                print('counter ' + str(x) + ' available')
                #que list
                customerid = que_list[0]
                #pop left of the quelist
                que_list.popleft()
                #get customer in que, record counter, start time
                served[x].append('customer ' + str(customerid))
                served[x].append('Start time: ' + str(int(time.time() - start_time)))
                await asyncio.sleep(randint(1,100))
                #record end time
                served[x].append('End time: ' + str(int(time.time() - start_time)))
                #set counter to true
                Counter_List[x] = True
                counter -= 1
                if total_customer == 10 and len(que_list) == 0:
                    #print the dictionary
                    print (served)
                    loop.stop()
            
loop = asyncio.get_event_loop()

try:
    asyncio.ensure_future(interarrival_time())
    asyncio.ensure_future(service_start())
    loop.run_forever()
finally:
    loop.close()

My output:我的 output:

customer 0 entered
customer 1 entered
customer 2 entered
customer 3 entered
customer 4 entered
customer 5 entered
customer 6 entered
customer 7 entered
customer 8 entered
customer 9 entered
counter 0 available
counter 1 available
counter 2 available
counter 3 available
counter 0 available
counter 1 available
counter 2 available
counter 3 available
counter 0 available
counter 1 available
defaultdict(<class 'list'>, {0: ['customer 0', 'Start time: 134', 'End time: 183', 'customer 4', 'Start time: 327', 'End time: 421', 'customer 8', 'Start time: 562', 'End time: 651'], 1: ['customer 1', 'Start time: 183', 'End time: 201', 'customer 5', 'Start time: 421', 'End time: 454', 'customer 9', 'Start time: 651', 'End time: 656'], 2: ['customer 2', 'Start time: 201', 'End time: 267', 'customer 6', 'Start time: 454', 'End time: 538'], 3: ['customer 3', 'Start time: 267', 'End time: 327', 'customer 7', 'Start time: 538', 'End time: 562']})

The 'customer x entered' and 'counter x available' are ways to keep track of if the system is running simultaneously. “客户 x 已进入”和“柜台 x 可用”是跟踪系统是否同时运行的方法。 I would like it so that it will be as an example:我想要它作为一个例子:

customer 1 entered
counter 0 available
customer 2 entered
counter 1 available
customer 3 entered
counter 2 available
customer 4 entered
counter 0 available
customer 5 entered
counter 3 available
customer 6 entered
customer 7 entered
counter 2 available 
and so on

What you want is asyncio.Queue for consumer-producer types of flows.您想要的是asyncio.Queue用于消费者-生产者类型的流。 Whenever a counter is free, it simply needs to ask the queue for the next customer .每当counter空闲时,它只需要询问queue中的下一位customer

import asyncio
import random

async def counter_task(customers: asyncio.Queue, counter_id: int) -> None:
    while True:
        # Get the next available customer.
        customer = await customers.get()
        print(f"Customer {customer} is being serviced at counter {counter_id}.")
        # Work on that customer.
        await asyncio.sleep(random.randint(1, 100))
        print(f"Customer {customer} has left counter {counter_id}.")
        # Signal the customer is done.
        customers.task_done()

async def main() -> None:
    customers = asyncio.Queue()
    counters = [asyncio.create_task(counter_task(customers, i)) for i in range(4)]
    try:
        # Create 10 customers.
        for customer in range(10):
            print(f"Customer {customer} has entered.")
            await customers.put(customer)
            await asyncio.sleep(random.randint(1, 25))
        # Wait for them to be signalled as finished.
        await customers.join()
    finally:
        # Stop the counters.
        for counter in counters:
            counter.cancel()
        for counter in counters:
            try:
                await counter
            except asyncio.CancelledError:
                pass

asyncio.run(main())

Sample output:样本 output:

Customer 0 has entered.
Customer 0 is being serviced at counter 0.
Customer 1 has entered.
Customer 1 is being serviced at counter 1.
Customer 2 has entered.
Customer 2 is being serviced at counter 2.
Customer 1 has left counter 1.
Customer 3 has entered.
Customer 3 is being serviced at counter 3.
Customer 4 has entered.
Customer 4 is being serviced at counter 1.
Customer 5 has entered.
Customer 0 has left counter 0.
Customer 5 is being serviced at counter 0.
Customer 6 has entered.
Customer 7 has entered.
Customer 4 has left counter 1.
Customer 6 is being serviced at counter 1.
Customer 8 has entered.
Customer 2 has left counter 2.
Customer 7 is being serviced at counter 2.
Customer 9 has entered.
Customer 3 has left counter 3.
Customer 8 is being serviced at counter 3.
Customer 7 has left counter 2.
Customer 9 is being serviced at counter 2.
Customer 5 has left counter 0.
Customer 6 has left counter 1.
Customer 8 has left counter 3.
Customer 9 has left counter 2.

If you don't care about overhead and memory in your app(it is not heavy) use Multi Threading.如果您不关心应用程序中的开销和 memory(它并不重),请使用多线程。 Although asyncio has the advantage of less overhead, but the codes which you use to write an asyncio program is very specific and it is very hard to use them in another app.尽管 asyncio 具有开销较小的优点,但是您用来编写 asyncio 程序的代码非常具体,很难在其他应用程序中使用它们。 For instance you can see in API frameworks, the developers develop the framework in 2 ways, ASGI(asyncio) and WSGI(not async)!!!!例如,您可以在 API 框架中看到,开发人员以 2 种方式开发框架,ASGI(asyncio)和 WSGI(非异步)!!!!

For example: https://falcon.readthedocs.io/en/stable/user/index.html例如: https://falcon.readthedocs.io/en/stable/user/index.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM