gpt4 book ai didi

python - 具有两个协程的asyncIO多线程服务器

转载 作者:行者123 更新时间:2023-12-03 13:03:10 25 4
gpt4 key购买 nike

我正在用Python3编程服务器,该服务器需要截图并通过websocket发送它。我有协程用于处理连接,我想创建另一个协程以在一定时间间隔内截取屏幕截图。屏幕快照协程可能会在不同的线程中运行,我将需要将结果传播到具有读写锁定的共享变量中,以便能够发送该结果。我的问题:(如果可能,结果应为多平台)

  • 如何安排这样的任务?我创建了可以永远运行的服务器,并且可以创建定期的协程,但是由于某种原因我无法将它们组合在一起。
  • 什么是将结果从一个线程(或协程,如果服务器是单线程)传播到另一个线程的好方法?

  • 我发现这段代码与此相似,但我无法使其正常工作(第二协程未执行)。有人可以在没有多线程的情况下进行纠正吗?
    async def print_var():
    global number
    await asyncio.sleep(2)
    print(number)


    async def inc_var():
    global number
    await asyncio.sleep(5)
    number += 1

    number = 0

    asyncio.get_event_loop().run_until_complete(print_var())
    asyncio.async(inc_var)
    asyncio.get_event_loop().run_forever()

    回答后编辑

    最后,经过更多小时的谷歌搜索,我实际上使它可以在单个线程上工作,因此没有竞争状况的危险。 (但是我仍然不确定sure_future会做什么,以及为什么没有在事件循环中调用它。)
    users = set()

    def register(websocket):
    users.add(websocket)

    def unregister(websocket):
    users.remove(websocket)

    async def get_screenshot():
    global screenshot
    while True:
    screenshot = screenshot()
    await asyncio.sleep(0.2)

    async def server(websocket, path):
    global screenshot
    register(websocket)
    try:
    async for message in websocket:
    respond(screenshot)
    finally:
    unregister(websocket)

    def main():
    asyncio.get_event_loop().run_until_complete(
    websockets.serve(server, 'localhost', 6789))
    asyncio.ensure_future(get_screenshot())
    asyncio.get_event_loop().run_forever()

    main()

    最佳答案

    在Python 3.7中:

    import asyncio

    import websockets

    CAPTURE_INTERVAL = 1
    running = True
    queues = set()


    async def handle(ws, path):
    queue = asyncio.Queue()
    queues.add(queue)
    while running:
    data = await queue.get()
    if not data:
    break
    await ws.send(data)


    def capture_screen():
    # Do some work here, preferably in C extension without holding the GIL
    return b'screenshot data'


    async def main():
    global running
    loop = asyncio.get_running_loop()
    server = await websockets.serve(handle, 'localhost', 8765)
    try:
    while running:
    data = await loop.run_in_executor(None, capture_screen)
    for queue in queues:
    queue.put_nowait(data)
    await asyncio.sleep(CAPTURE_INTERVAL)
    finally:
    running = False
    for queue in queues:
    queue.put_nowait(None)
    server.close()
    await server.wait_closed()


    if __name__ == '__main__':
    asyncio.run(main())

    请注意,这仅用于演示生产者-消费者扇出模式。 queues不是必需的-您可以直接将 data发送到 server.sockets中的所有 main()中,而在 handle()中,您应该担心传入的Websocket消息。例如,客户端可以像这样控制图像压缩率:
    import asyncio

    import websockets

    CAPTURE_INTERVAL = 1
    DEFAULT = b'default'
    qualities = {}


    async def handle(ws, path):
    try:
    async for req in ws:
    qualities[ws] = req
    finally:
    qualities.pop(ws, None)


    def capture_screen():
    # Do some work here, preferably in C extension without holding the GIL
    return {
    DEFAULT: b'default screenshot data',
    b'60': b'data at 60% quality',
    b'80': b'data at 80% quality',
    }


    async def main():
    loop = asyncio.get_running_loop()
    server = await websockets.serve(handle, 'localhost', 8765)
    try:
    while True:
    data = await loop.run_in_executor(None, capture_screen)
    for ws in server.sockets:
    quality = qualities.get(ws, DEFAULT)
    if quality not in data:
    quality = DEFAULT
    asyncio.create_task(ws.send(data[quality]))
    await asyncio.sleep(CAPTURE_INTERVAL)
    finally:
    server.close()
    await server.wait_closed()


    if __name__ == '__main__':
    asyncio.run(main())

    关于python - 具有两个协程的asyncIO多线程服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51548025/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com