[Python-ideas] Async API

Yury Selivanov yselivanov.ml at gmail.com
Tue Oct 30 02:00:46 CET 2012


Oh... I'm sorry for the empty reply.

On 2012-10-29, at 8:06 PM, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
> Yury Selivanov wrote:
>> Because scheduler, when it is deciding to interrupt a coroutine or not, should only question whether that particular coroutine is in its finally, and not the one which called it.
> 
> So given this:
> 
>   def c1():
>      try:
>         something()
>      finally:
>         yield from c2()
>         very_important_cleanup()
> 
>   def c2():
>      yield from block() # 1
> 
> it should be okay to interrupt at point 1, even though
> it will prevent very_important_cleanup() from being done?
> 
> That doesn't seem right to me.

But you don't just randomly interrupt coroutines.  You interrupt them
when you *explicitly stated*, for instance, that this very one coroutine
is executed with a timeout.  And it's your responsibility to handle
a TimeoutError when you call it with such restriction.

That's the *main* thing here.  Again, when you, explicitly, execute 
something with a timeout), then that very something shouldn't be 
interrupted uncontrollably by the scheduler.  It's that particular
something, whose 'finally' should be protected.

So in your example scheduler would never ever has a question of 
interrupting c2(), because it wasn't called with any restriction/timeout.
There simply no reason to interrupt it ever.

But if you want to make c2() interruptible, you would write:

   def c1():
       try:
          something()
       finally:
          yield from with_timeout(2.0, c2())
          very_important_cleanup()

And that way, c2() actually may be (and at some point will be) interrupted
by scheduler.  And it's your responsibility to catch TimeoutError.

So you would write your code in the following way to protect c1's finally 
statement:

   def c1():
       try:
          something()
       finally:
          try:
             yield from with_timeout(2.0, c2())
          except TimeoutError:
             ...
          very_important_cleanup()

Now, the problem is that when you call c2() with a timeout, scheduler should
not interrupt c2's finally statement (if there is any).  And it has nothing 
to do with c1 entirely.

So if c2() code is like the following:

   def c2():
       try:
          something()
       finally:
          yield from someotherthing()
          important_cleanup()

Then you need scheduler to know if it is in its finally or not.  Because its
c2() which was run with a timeout.  It's c2() code that may be subject to
aborting.  And it doesn't matter from where c2() was called, the only thing
that matters, is that if it was called with a timeout, its finally block
should be protected from interrupting.  That's all.

-
Yury


More information about the Python-ideas mailing list