1

I am trying to build a Server and Client using Python Websockets library. I am following the example given here: Python OCPP documentation. I want to edit this example such that for each new client(Charge Point), the server(Central System) runs on new thread (or new loop as Websockets library uses Python's asyncio). Basically I want to receive messages from multiple clients simultaneously. I modified the main method of server(Central System), from the example that I followed, like this by adding a loop parameter in websockets.serve() in a hope that whenever a new client runs, it runs on a different loop:

async def main():
    server = await websockets.serve(
        on_connect,
        '0.0.0.0',
        9000,
        subprotocols=['ocpp2.0'],
        ssl=ssl_context,
        loop=asyncio.new_event_loop(),
        ping_timeout=100000000      
    )


    await server.wait_closed()

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

I am getting the following error. Please help:

RuntimeError: 
    Task <Task pending coro=<main() running at server.py:36> 
    cb=_run_until_complete_cb() at /usr/lib/python3.7/asyncio/base_events.py:153]> 
got Future <_GatheringFuture pending> attached to a different loop - sys:1: 
RuntimeWarning: coroutine 'BaseEventLoop._create_server_getaddrinfo' was never awaited
PirateNinjas
  • 1,908
  • 1
  • 16
  • 21
  • *For each new client, I want the server to run on new thread* - Why, what problem are you trying to solve? Asyncio is inherently single-threaded and there is normally no need to start multiple threads or multiple event loops. – user4815162342 Apr 26 '20 at 10:52
  • Yeah but I want the server to simultaneously receive messages from multiple clients and it won't be possible unless I run server with multiple loops. Or is there another way? Thanks. – Raghav Gupta Apr 26 '20 at 11:45
  • There is almost certainly another way. Please edit the question to include your actual use case, otherwise we're dealing with an [xy problem](http://xyproblem.info/). – user4815162342 Apr 26 '20 at 11:47
  • I am following the example given here (https://pypi.org/project/ocpp/). The Central System is my server and Charge Point is my client as given in the example in above link. I want to receive messages from multiple Charge Points simultaneously on the Central System. Thanks in advance! – Raghav Gupta Apr 26 '20 at 16:14
  • The example looks like it supports multiple charge points already. It creates a central system, and whenever a charge point connects, `on_connect` is spawned. What do you need on top of that? – user4815162342 Apr 26 '20 at 18:55
  • The whole point of `ayncio` is to have concurrency without multiple OS threads. This is actually better than true multithreading, because Python has the dreaded [GIL](https://wiki.python.org/moin/GlobalInterpreterLock), which prevents it from interpreting bytecode in multiple threads simultatenously. – Hristo Iliev Apr 27 '20 at 23:08

1 Answers1

1

Author of the OCPP package here. The examples in the project are able to handle multiple clients with 1 event loop.

The problem in your example is loop=asyncio.new_event_loop(). The websocket.serve() is called in the 'main' event loop. But you pass it a reference to a second event loop. This causes the future to be attached to a different event loop it was created it.

You should avoid running multiple event loops.

OrangeTux
  • 11,142
  • 7
  • 48
  • 73