Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-20 Thread Alexander Belopolsky
On Fri, Dec 18, 2015 at 4:09 PM, Guido van Rossum  wrote:

>
>> It's 11 days. Which is pretty reasonable server uptime.
>>
>
> Oops, blame the repr() of datetime.timedelta. I'm sorry I so rashly
> thought I could do better than the OP.
>

A helpful trivia: a year is approximately π times 10 million seconds.
___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-20 Thread Sven R. Kunze

On 18.12.2015 22:09, Guido van Rossum wrote:
I guess we could make the default arg to sleep() 1e9. Or make it None 
and special-case it. I don't feel strongly about this -- I'm not sure 
how baffling it would be to accidentally leave out the delay and find 
your code sleeps forever rather than raising an error (since if you 
don't expect the infinite default you may not expect this kind of 
behavior). But I do feel it's not important enough to add a new 
function or method.


Why still guessing the best surrogate for infinity?

Seems like python is just missing int('inf'). :/

Best,
Sven
___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Guido van Rossum
Using an Event is slightly better because you just wait for it -- you don't
have to catch an exception. It's just not one of the better-known parts of
asyncio.

On Fri, Dec 18, 2015 at 1:42 PM, Andrew Barnert  wrote:

> On Friday, December 18, 2015 1:09 PM, Guido van Rossum 
> wrote:
>
>
> >I guess we could make the default arg to sleep() 1e9. Or make it None and
> special-case it. I don't feel strongly about this -- I'm not sure how
> baffling it would be to accidentally leave out the delay and find your code
> sleeps forever rather than raising an error (since if you don't expect the
> infinite default you may not expect this kind of behavior).
>
> Yeah, that is a potential problem.
>
> The traditional C solution is to just allow passing -1 to mean "forever",*
> ideally with a constant so you can just say "sleep(FOREVER)". Which, in
> Python terms, would presumably mean "asyncio.sleep(asyncio.forever)", and
> it could be a unique object or an enum value or something instead of
> actually being -1.
>
> * Or at least "until this rolls over 31/32/63/64 bits", which is where you
> get those 49-day bugs from... but that wouldn't be an issue in Python
>
> > But I do feel it's not important enough to add a new function or method.
>
> Definitely agreed.
> >However, I don't think "forever" and "until cancelled" are really the
> same thing. "Forever" can only be interrupted by loop.stop(); "until
> cancelled" requires indicating how to cancel it, and there the OP's
> approach is about the best you can do. (Or you could use the Event class,
> but that's really just a wrapper on top of a Future made to look more like
> threading.Event in its API.)
>
>
> OK, I thought the OP's code looked pretty clear as written: he wants to
> wait until cancelled, so he waits on something that pretty clearly won't
> ever finish until he's cancelled. If that (or an Event or whatever) is the
> best way to spell this, then I can't really think of any good uses for
> sleep(forever).
>



-- 
--Guido van Rossum (python.org/~guido)
___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Andrew Barnert via Python-Dev
On Friday, December 18, 2015 1:09 PM, Guido van Rossum  wrote:


>I guess we could make the default arg to sleep() 1e9. Or make it None and 
>special-case it. I don't feel strongly about this -- I'm not sure how baffling 
>it would be to accidentally leave out the delay and find your code sleeps 
>forever rather than raising an error (since if you don't expect the infinite 
>default you may not expect this kind of behavior).

Yeah, that is a potential problem.

The traditional C solution is to just allow passing -1 to mean "forever",* 
ideally with a constant so you can just say "sleep(FOREVER)". Which, in Python 
terms, would presumably mean "asyncio.sleep(asyncio.forever)", and it could be 
a unique object or an enum value or something instead of actually being -1.

* Or at least "until this rolls over 31/32/63/64 bits", which is where you get 
those 49-day bugs from... but that wouldn't be an issue in Python

> But I do feel it's not important enough to add a new function or method.

Definitely agreed.
>However, I don't think "forever" and "until cancelled" are really the same 
>thing. "Forever" can only be interrupted by loop.stop(); "until cancelled" 
>requires indicating how to cancel it, and there the OP's approach is about the 
>best you can do. (Or you could use the Event class, but that's really just a 
>wrapper on top of a Future made to look more like threading.Event in its API.)


OK, I thought the OP's code looked pretty clear as written: he wants to wait 
until cancelled, so he waits on something that pretty clearly won't ever finish 
until he's cancelled. If that (or an Event or whatever) is the best way to 
spell this, then I can't really think of any good uses for sleep(forever).
___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Szieberth Ádám
> I guess we could make the default arg to sleep() 1e9. Or make it None and
> special-case it.

By writing the OP, I considered suggesting this approach and rejected. I would 
have suggest the  using Ellipsis (`...`) for the special case which seemed to 
explain more what is done plus it can hardly given unintentionally. I ended up 
suggesting `wait_forever()` though.

Á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/archive%40mail-archive.com


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Szieberth Ádám
> Maybe you can help by submitting a patch that prevents this error! Are you
> interested?

I'd be honored.

Ádám
(http://szieberthadam.github.io/)

P.S.: Was thinking about a longer answer but finally I ended up with this one :)
___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Szieberth Ádám
Thanks for your reply Andrew!

> 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?

Indeed. I was prepared for such opinions which is OK. It is better to think it 
through several times twice before introducing a new feature to an API.

I myself feel that `loop.create_context_task()` may be too specific. The 
`asyncio.wait_forever()` coro seems much simple. Surely it must get 
investigated whether there are a significal amount of patterns where this coro 
could take part. I introduced one but surely that is not enough, only if it is 
so awesome that everyone starts using it which I doubt. :)

Á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/archive%40mail-archive.com


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Guido van Rossum
On Fri, Dec 18, 2015 at 12:45 PM, Andrew Barnert  wrote:

> On Dec 18, 2015, at 10:36, Guido van Rossum  wrote:
>
> On Fri, Dec 18, 2015 at 10:25 AM, Szieberth Ádám 
> wrote:
>
>> Thanks for your reply Guido!
>>
>> > - In theory, instead of waiting for a Future that is cancelled by a
>> > handler, you should be able to use asyncio.sleep() with a very large
>> number
>> > (e.g. a million seconds).
>>
>> I was thinking on this too but it seemed less explicit to me than
>> awaiting a
>> pure Future with a short comment. Moreover, even millions of seconds can
>> pass.
>>
>
> 11 years.
>
>
> It's 11 days. Which is pretty reasonable server uptime.
>

Oops, blame the repr() of datetime.timedelta. I'm sorry I so rashly thought
I could do better than the OP.


> And probably just outside the longest test you're ever going to run. I
> don't trust myself to pick "a big number" when the numbers get this big.
> But I still sometimes sneak one past myself somehow. Hence my suggestion
> for a way to actually say "forever".
>

I guess we could make the default arg to sleep() 1e9. Or make it None and
special-case it. I don't feel strongly about this -- I'm not sure how
baffling it would be to accidentally leave out the delay and find your code
sleeps forever rather than raising an error (since if you don't expect the
infinite default you may not expect this kind of behavior). But I do feel
it's not important enough to add a new function or method.

However, I don't think "forever" and "until cancelled" are really the same
thing. "Forever" can only be interrupted by loop.stop(); "until cancelled"
requires indicating how to cancel it, and there the OP's approach is about
the best you can do. (Or you could use the Event class, but that's really
just a wrapper on top of a Future made to look more like threading.Event in
its API.)

-- 
--Guido van Rossum (python.org/~guido)
___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Andrew Barnert via Python-Dev
On Dec 18, 2015, at 10:36, Guido van Rossum  wrote:
> 
>> On Fri, Dec 18, 2015 at 10:25 AM, Szieberth Ádám  wrote:
>> Thanks for your reply Guido!
>> 
>> > - In theory, instead of waiting for a Future that is cancelled by a
>> > handler, you should be able to use asyncio.sleep() with a very large number
>> > (e.g. a million seconds).
>> 
>> I was thinking on this too but it seemed less explicit to me than awaiting a
>> pure Future with a short comment. Moreover, even millions of seconds can 
>> pass.
> 
> 11 years.

It's 11 days. Which is pretty reasonable server uptime. And probably just 
outside the longest test you're ever going to run. I don't trust myself to pick 
"a big number" when the numbers get this big. But I still sometimes sneak one 
past myself somehow. Hence my suggestion for a way to actually say "forever".

___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Andrew Barnert via Python-Dev
On Dec 18, 2015, at 10:25, Szieberth Ádám  wrote:
> 
>> - In theory, instead of waiting for a Future that is cancelled by a
>> handler, you should be able to use asyncio.sleep() with a very large number
>> (e.g. a million seconds).
> 
> I was thinking on this too but it seemed less explicit to me than awaiting a 
> pure Future with a short comment. Moreover, even millions of seconds can pass.

Yes, and these are really fun to debug. When a customer comes to you with "it 
was running fine for a few months and then suddenly it started going crazy, but 
I can't reproduce it", unless you happen to remember that you decided 10 
million seconds was "forever" and ask whether "a few months" specifically means 
a few days short of 4 months... (At least with 24 and 49 days I know to look 
for which library used a C integer for milliseconds.)

Really, I don't see anything wrong with the way the OP wrote it. Is that just 
because I have bad C habits (/* Useless select because there's no actual sleep 
function that allows SIGUSR to wake us without allowing all signals to wake us 
that works on both Solaris and IRIX */) and it really does look misleading to 
people who aren't warped like that?

If so, would it be worth having an actual way to say "sleep forever (until 
canceled)"? Even if, under the covers, this only sleeps for 5 years or so, 
a Y52K problem that can be solved by just pushing a new patch release for 
Python instead of for every separate server written in Python is probably a bit 
nicer. :)
___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Guido van Rossum
No, it just means Windows users should not try to catch signals on Windows.

Signals don't really exist there, and the simulation supporting only a few
signals is awful (last I tried ^C was only processed when the process was
waiting for input from stdin, and I had to use the BREAK key to stop
runaway processes, which killed my shell window as well as the Python
process).

If you want orderly shutdown of a server process on Windows, you should
probably listen for connections on a dedicated port on localhost and use
that as an indication to stop the server.

On Fri, Dec 18, 2015 at 11:29 AM, Glenn Linderman 
wrote:

> On 12/18/2015 10:36 AM, Guido van Rossum wrote:
>
> I was opted to the signal module because `signal` documentation suggest
>> that
>> it alos supports Windows while asyncio documentation states that `loop.
>> add_signal_handler()` is UNIX only.
>>
>
> Unfortunately that's true, but using the signal module with asyncio the
> way you did is *not* safe. The only safe way is to use the
> loop.add_signal_handler() interface.
>
>
> Does this mean Windows users should not bother trying to use asyncio ?
>
> (I haven't yet, due to lack of time, but I'd hate to think of folks,
> including myself in the future, investing a lot of time developing
> something and then discover it can never be reliable, due to this sort of
> "unsafe" or "not-available-on-Windows" feature.)
>
> ___
> 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/guido%40python.org
>
>


-- 
--Guido van Rossum (python.org/~guido)
___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Glenn Linderman

On 12/18/2015 10:36 AM, Guido van Rossum wrote:


I was opted to the signal module because `signal` documentation
suggest that
it alos supports Windows while asyncio documentation states that
`loop.
add_signal_handler()` is UNIX only.


Unfortunately that's true, but using the signal module with asyncio 
the way you did is *not* safe. The only safe way is to use the 
loop.add_signal_handler() interface.


Does this mean Windows users should not bother trying to use asyncio ?

(I haven't yet, due to lack of time, but I'd hate to think of folks, 
including myself in the future, investing a lot of time developing 
something and then discover it can never be reliable, due to this sort 
of "unsafe" or "not-available-on-Windows" feature.)
___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Guido van Rossum
On Fri, Dec 18, 2015 at 10:25 AM, Szieberth Ádám 
wrote:

> Thanks for your reply Guido!
>
> > - Instead of calling signal.signal() yourself, you should use
> > loop.add_signal_handler(). It makes sure your signal handler doesn't run
> > while another handler is already running.
>
> I was opted to the signal module because `signal` documentation suggest
> that
> it alos supports Windows while asyncio documentation states that `loop.
> add_signal_handler()` is UNIX only.
>

Unfortunately that's true, but using the signal module with asyncio the way
you did is *not* safe. The only safe way is to use the
loop.add_signal_handler() interface.


> > - I'm unclear on why you want a wait_forever() instead of using
> > loop.run_forever(). Can you clarify?
>
> As I see `loop.run_forever()` is an issue from _outside_ while an `await
> wait_forever()` would be an _inside_ declaration making explicit what the
> task
> does (serving forever).
>
> My OP suggest that it seemed to me quite helpful inside async context.
> However, I wanted to share my approach to get a confirmation that I am not
> on
> a totally wrong way with this.
>

Well, if you look at the toy servers in the asyncio examples directory,
they all use run_forever(). I agree that from within the loop that's not
possible, but I don't think it's such a common thing (you typically write a
framework for creating servers once and that's the only place where you
would need this). IOW I think your solution of waiting for a Future is the
right way.


> > - In theory, instead of waiting for a Future that is cancelled by a
> > handler, you should be able to use asyncio.sleep() with a very large
> number
> > (e.g. a million seconds).
>
> I was thinking on this too but it seemed less explicit to me than awaiting
> a
> pure Future with a short comment. Moreover, even millions of seconds can
> pass.
>

11 years. That's quite some trust you put in your hardware... But you can
use a billion. I think by 11000 years from now you can retire your server.
:-)


> > Your handler could then just call loop.stop().
>
> For some reason I don't like bothering with the event loop from inside
> awaitables. It seems hacky to me since it breaks the hierarhy of who
> controlls
> who.
>

Fair enough -- you've actually internalized the asyncio philosophy quite
well.


> > However, I just tested this and it raises "RuntimeError: Event loop
> stopped
> > before Future completed." so ignore this until we've fixed it. :-)
>
> This is the exception I saw so many times by trying to close an asyncio
> program! I guess I am not the only one. This may be one of the most
> frustrating aspects of the library. Yet, it inspired me to figure out a
> plain
> pattern to avoid it, which may not the right one. However, I would like to
> signal that it would be nice to help developers with useful patterns and
> documentation to avoid RuntimeErrors and the frustration that goes with
> them.
>

Maybe you can help by submitting a patch that prevents this error! Are you
interested?


> Ádám
> (http://szieberthadam.github.io/)
>
> PS: I will replay to others as well, but first I had to play with my son.
> :)
>



-- 
--Guido van Rossum (python.org/~guido)
___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Szieberth Ádám
Thanks for your reply Guido!

> - Instead of calling signal.signal() yourself, you should use
> loop.add_signal_handler(). It makes sure your signal handler doesn't run
> while another handler is already running.

I was opted to the signal module because `signal` documentation suggest that 
it alos supports Windows while asyncio documentation states that `loop.
add_signal_handler()` is UNIX only.

> - I'm unclear on why you want a wait_forever() instead of using
> loop.run_forever(). Can you clarify?

As I see `loop.run_forever()` is an issue from _outside_ while an `await 
wait_forever()` would be an _inside_ declaration making explicit what the task 
does (serving forever).

My OP suggest that it seemed to me quite helpful inside async context. 
However, I wanted to share my approach to get a confirmation that I am not on 
a totally wrong way with this.

> - In theory, instead of waiting for a Future that is cancelled by a
> handler, you should be able to use asyncio.sleep() with a very large number
> (e.g. a million seconds). 

I was thinking on this too but it seemed less explicit to me than awaiting a 
pure Future with a short comment. Moreover, even millions of seconds can pass.

> Your handler could then just call loop.stop().

For some reason I don't like bothering with the event loop from inside 
awaitables. It seems hacky to me since it breaks the hierarhy of who controlls 
who.

> However, I just tested this and it raises "RuntimeError: Event loop stopped
> before Future completed." so ignore this until we've fixed it. :-)

This is the exception I saw so many times by trying to close an asyncio 
program! I guess I am not the only one. This may be one of the most 
frustrating aspects of the library. Yet, it inspired me to figure out a plain 
pattern to avoid it, which may not the right one. However, I would like to 
signal that it would be nice to help developers with useful patterns and 
documentation to avoid RuntimeErrors and the frustration that goes with them.

Ádám
(http://szieberthadam.github.io/)

PS: I will replay to others as well, but first I had to play with my son. :)
___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread R. David Murray
On Fri, 18 Dec 2015 18:29:35 +0200, Andrew Svetlov  
wrote:
> 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?

In my own asyncio code I wrote a generic context manager to hold
references to all the top level tasks my ap needs, which automatically
handles the teardown when loop.stop() is called from my SIGTERM
signal handler.

However, (and here we get to the python-dev content of this post :), I
think we are too early in the uptake of asyncio to be ready to say what
additional high-level features are well defined enough and useful enough
to become part of the standard library.  In any case discussions like
this really belong on the asyncio-specific mailing list, which I gather
is the python-tulip Google Group (I suppose I really ought to sign up...)

--David
___
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


Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Guido van Rossum
I agree with Andrew that there are too many different scenarios and
requirements to make this a useful library function. Some notes on the
actual code you posted:

- Instead of calling signal.signal() yourself, you should use
loop.add_signal_handler(). It makes sure your signal handler doesn't run
while another handler is already running.

- If you add a handler for SIGINT you can control what happens when the
user hits ^C (again, ensuring the handler already running isn't interrupted
halfway through).

- I'm unclear on why you want a wait_forever() instead of using
loop.run_forever(). Can you clarify?

- In theory, instead of waiting for a Future that is cancelled by a
handler, you should be able to use asyncio.sleep() with a very large number
(e.g. a million seconds). Your handler could then just call loop.stop().
However, I just tested this and it raises "RuntimeError: Event loop stopped
before Future completed." so ignore this until we've fixed it. :-)

On Fri, Dec 18, 2015 at 5:58 AM, Szieberth Ádám  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/guido%40python.org
>



-- 
--Guido van Rossum (python.org/~guido)
_

Re: [Python-Dev] Asynchronous context manager in a typical network server

2015-12-18 Thread Andrew Svetlov
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  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