I my asyncio code typical initialization/finalization procedures are much more complicated. I doubt if common code can be extracted into asyncio. Personally I don't feel the need for `wait_forever()` or `loop.creae_context_task()`.
But even if you need it you may create it from scratch easy, isn't it? On Fri, Dec 18, 2015 at 3:58 PM, Szieberth Ádám <szieba...@gmail.com> wrote: > Hi Developers! > > This is my first post. Please excuse me my poor English. If anyone is > interested, I wrote a small introduction on my homepage. Link is at the > bottom. > > This post is about how to effectively implement the new asynchronous context > manager in a typical network server. > > I would appreciate and welcome any confirmation or critics whether my thinking > is right or wrong. Thanks in advance! > > So, a typical server main code I used to see around is like this: > > srv = loop.run_until_complete(create_server(handler, host, port)) > try: > loop.run_forever() > except KeyboardInterrupt: > pass > finally: > # other tear down code may be here > srv.close() > loop.run_until_complete(srv.wait_closed()) > loop.close() > > Note that `create_server()` here is not necessary > `BaseEventLoop.create_server()`. > > The above code is not prepared to handle `OSError`s or any other `Exception`s > (including a `KeyboardInterrupt` by a rapid Ctr+C) when setting up the server, > it just prints the traceback to the console which is not user friendly. > Moreover, I would expect from a server to handle the SIGTERM signal as well > and tell its clients that it stops serving when not force killed. > > How the main code should create server, maintain the serving, deal with errors > and close properly both the connections and the event loop when exiting > without letting pending tasks around is not trivial. There are many questions > on SO and other places of the internet regarding of this problem. > > My idea was to provide a simple code which is robust in terms of these > concerns by profiting from the new asynchronous context manager pattern. > > The code of the magic methods of a typical awaitable `CreateServer` object > seems rather trivial: > > async def __aenter__(self): > self.server = await self > return self.server > > async def __aexit__(self, exc_type, exc_value, traceback): > # other tear down code may be here > self.server.close() > await self.server.wait_closed() > > However, to make it work, a task has to be created: > > async def server_task(): > async with CreateServer(handler, host, port) as srv: > await asyncio.Future() # wait forever > > I write some remarks regarding the above code to the end of this post. Note > that `srv` is unreachable from outside which could be a problem in some cases. > What is unavoidable: this task has to get cancelled explicitely by the main > code which should look like this: > > srvtsk = loop.create_task(server_task()) > > signal.signal(signal.SIGTERM, lambda si, fr: > loop.call_soon(srvtsk.cancel)) > > while True: > try: > loop.run_until_complete(srvtsk) > except KeyboardInterrupt: > srvtsk.cancel() > except asyncio.CancelledError: > break > except Exception as err: > print(err) > break > loop.close() > > Note that when `CancelledError` gets raised, the tear down process is already > done. > > Remarks: > > * It would be nice to have an `asyncio.wait_forever()` coroutine for dummy > context bodies. > * Moreover, I also imagined an `BaseEventLoop.create_context_task(awithable, > body_coro_func=None)` method. The `body_coro_func` should default to > `asyncio.wait_forever()`, otherwise it should get whatever is returned by > `__aenter__` as a single argument. The returned Task object should also > provide a reference to that object. > > Best regards, > Ádám > > (http://szieberthadam.github.io/) > _______________________________________________ > Python-Dev mailing list > Python-Dev@python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > https://mail.python.org/mailman/options/python-dev/andrew.svetlov%40gmail.com -- Thanks, Andrew Svetlov _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com