Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x Python:manager.Queue()和asyncio。如何解决僵局?_Python 3.x_Websocket_Queue_Python Asyncio_Python Multiprocessing - Fatal编程技术网

Python 3.x Python:manager.Queue()和asyncio。如何解决僵局?

Python 3.x Python:manager.Queue()和asyncio。如何解决僵局?,python-3.x,websocket,queue,python-asyncio,python-multiprocessing,Python 3.x,Websocket,Queue,Python Asyncio,Python Multiprocessing,我试图弄清楚如何让基于websocket的服务器侦听传入的请求,将它们放入另一个进程工作的队列中,然后将结果放入另一个队列中,基于websocket的服务器可以在该队列中等待所述结果并将响应发送回客户端 这只是我在尝试学习异步IO和在进程之间共享数据并获得更多经验。我使用的是Python3.9.2 64位 现在我陷入了死锁,正如服务器代码中“producer\u handler”函数中所述。以下是我正在使用的代码: 服务器: import asyncio import logging impor

我试图弄清楚如何让基于websocket的服务器侦听传入的请求,将它们放入另一个进程工作的队列中,然后将结果放入另一个队列中,基于websocket的服务器可以在该队列中等待所述结果并将响应发送回客户端

这只是我在尝试学习异步IO和在进程之间共享数据并获得更多经验。我使用的是Python3.9.2 64位

现在我陷入了死锁,正如服务器代码中“producer\u handler”函数中所述。以下是我正在使用的代码:

服务器:

import asyncio
import logging
import time
from multiprocessing import Manager, Process
import websockets

logging.root.setLevel(0)



def server(recievequeue, sendqueue):


    async def consumer_handler(websocket, path):
        while True:
            logging.info('Waiting for request')
            try:
                request = await websocket.recv()
            except Exception as exception:
                logging.warning(f'consumer_handler Error: {exception}')
                break
            logging.info(f'Request: {request}')
            recievequeue.put(request)
            logging.info('Request placed in recievequeue')


    async def producer_handler(websocket, path):
        while True:
            logging.info('Waiting for response')
            response = sendqueue.get()# Deadlock is here.
            try:
                await websocket.send(response)
            except Exception as exception:
                logging.warning(f'producer_handler Error: {exception}')
                break
            logging.info('Response sent')


    async def handler(websocket, path):
        consumer_task = asyncio.ensure_future(consumer_handler(websocket, path))
        producer_task = asyncio.ensure_future(producer_handler(websocket, path))

        done, pending = await asyncio.wait([producer_task, consumer_task], return_when=asyncio.FIRST_COMPLETED)

        for task in done:
            logging.info(f'Canceling: {task}')
            task.cancel()

        for task in pending:
            logging.info(f'Canceling: {task}')
            task.cancel()


    eventloop = asyncio.get_event_loop()
    eventloop.run_until_complete(websockets.serve(handler, 'localhost', 8081, ssl=None))
    eventloop.run_forever()



def message_handler(recievequeue, sendqueue):
    while True:
        # I just want to test getting a message from the recievequeue, and placing it in the sendqueue
        request = recievequeue.get()
        logging.info(f'Request: {request}')
        time.sleep(3)
        data = str(time.time())
        logging.info(f'Work completed @ {data}')
        sendqueue.put(data)



def main():
    logging.info('Starting Application')

    manager = Manager()
    sendqueue = manager.Queue()
    recievequeue = manager.Queue()

    test_process_1 = Process(target=server, args=(recievequeue, sendqueue), name='Server')
    test_process_1.start()

    test_process_2 = Process(target=message_handler, args=(recievequeue, sendqueue), name='Message Handler')
    test_process_2.start()

    test_process_1.join()



if __name__ == '__main__':
    main()

客户:

import asyncio
import logging
import websockets

logging.root.setLevel(0)
URI = "wss://localhost:8081"



async def test():


    async def consumer_handler(connection):
        while True:
            try:
                request = await connection.recv()
            except Exception as exception:
                logging.warning(f'Error: {exception}')
                break
            logging.info(request)


    async def producer_handler(connection):
        while True:
            await asyncio.sleep(5)
            try:
                await connection.send('Hello World')
            except Exception as exception:
                logging.warning(f'Error: {exception}')
                break


    async with websockets.connect(URI, ssl=None) as connection:
        consumer_task = asyncio.ensure_future(consumer_handler(connection))
        producer_task = asyncio.ensure_future(producer_handler(connection))
        while True:
            await asyncio.wait([consumer_task, producer_task], return_when=asyncio.FIRST_COMPLETED)



def main():
    logging.info('Starting Application')

    eventloop = asyncio.get_event_loop()

    try:
        eventloop.run_until_complete(test())
        eventloop.run_forever()
    except Exception as exception:
        logging.warning(f'Error: {exception}')



if __name__ == '__main__':
    main()


如果我删除队列,服务器和多个客户机就可以不出问题地来回交谈。我就是不知道如何获取()和放置()请求和响应。任何帮助都将不胜感激

所以在浏览了其他帖子后,我注意到其他人在谈论死锁和使用
run\u in\u executor
。经过进一步测试,我发现用以下代码替换导致死锁的行解决了问题:

response = await eventloop.run_in_executor(None, sendqueue.get)

您需要等待
get
put
。您还应该使用
asyncio.sleep
而不是
time.sleep
。如果我在sendqueue.get()之前添加了一点延迟(wait asyncio.sleep(20)),那么在尝试等待get和put时会出现以下错误:exception=TypeError(“object NoneType不能在'wait'表达式中使用”)。啊,听起来您没有使用
asyncio.Queue
。我错过了。你为什么要混合使用多处理和异步IO而不是只使用一个呢?我试图学习如何处理单独的进程管理工作,而websocket服务器只需要管理从客户端发送和接收消息。这只是一个更好地理解复杂系统的个人项目。
run\u in\u executor
将起作用,但请注意,它在引擎盖下使用线程,因此您最终会同时拥有线程和进程。一个可能更简单的解决方案是实例化一个
concurrent.futures.ProcessPoolExecutor
,并在需要一个进程执行某些任务时使用
run\u in\u executor
。然后,队列由
concurrent.futures
隐式处理,因此这种方法比生成您自己的子流程要简单一些,但它可能更简单,并且由asyncio直接支持。