On Sun, Oct 7, 2012 at 12:05 AM, Guido van Rossum <gu...@python.org> wrote:
> However I figured that if we define the interfaces well enough, it
> might be possible to use (a superficially modified version of)
> Twisted's reactors instead of the standard ones, and, orthogonally,
> Twisted's deferred's could be wrapped in the standard Futures (or the
> other way around?) when used with a non-Twisted reactor. Which would
> hopefully open the door for migrating some of their more useful
> protocol parsers into the stdlib.
I thought futures were meant for thread and process pools? The
blocking methods make them a bad fit for an asynchronous networking
toolset.
The Twisted folks have discussed integrating futures and Twisted (see
also the reply, which has some corrections):
http://twistedmatrix.com/pipermail/twisted-python/2011-January/023296.html
-- Devin
> If there's one take away idea from async-pep, it's reusable protocols.Is there a newer version that what's on
http://www.python.org/dev/peps/pep-3153/ ? It seems to be missing any
specific proposals, after spending a lot of time giving a rationale
and defining some terms. The version on
https://github.com/lvh/async-pep doesn't seem to be any more complete.
> The PEP should probably be a number of PEPs. At first sight, it seems thatBut the devil is in the details. *What* specifically are you
> this number is at least four:
>
> 1. Protocol and transport abstractions, making no mention of asynchronous IO
> (this is what I want 3153 to be, because it's small, manageable, and
> virtually everyone appears to agree it's a fantastic idea)
proposing? How would you write a protocol handler/parser without any
reference to I/O? Most protocols are two-way streets -- you read some
stuff, and you write some stuff, then you read some more. (HTTP may be
the exception here, if you don't keep the connection open.)
> 2. A base reactor interfaceI agree that this should be a separate PEP. But I do think that in
practice there will be dependencies between the different PEPs you are
proposing.
> 3. A way of structuring callbacks: probably deferreds with a built-inYour previous two ideas sound like you're not tied to backward
> inlineCallbacks for people who want to write synchronous-looking code with
> explicit yields for asynchronous procedures
compatibility with Tornado and/or Twisted (not even via an adaptation
layer). Given that we're talking Python 3.4 here that's fine with me
(though I think we should be careful to offer a path forward for those
packages and their users, even if it means making changes to the
libraries).
But Twisted Deferred is pretty arcane, and I would much
rather not use it as the basis of a forward-looking design. I'd much
rather see what we can mooch off PEP 3148 (Futures).
> 4+ adapting the stdlib tools to using these new thingsWe at least need to have an idea for how this could be done. We're
talking serious rewrites of many of our most fundamental existing
synchronous protocol libraries (e.g. httplib, email, possibly even
io.TextWrapper), most of which have had only scant updates even
through the Python 3 transition apart from complications to deal with
the bytes/str dichotomy.
> Re: forward path for existing asyncore code. I don't remember this beingI have the feeling that the main reason asyncore sucks is that it
> raised as an issue. If anything, it was mentioned in passing, and I think
> the answer to it was something to the tune of "asyncore's API is broken,
> fixing it is more important than backwards compat". Essentially I agree with
> Guido that the important part is an upgrade path to a good third-party
> library, which is the part about asyncore that REALLY sucks right now.
requires you to subclass its Dispatcher class, which has a rather
treacherous interface.
> Regardless, an API upgrade is probably a good idea. I'm not sure if itAren't all your proposals API upgrades?
> should go in the first PEP: given the separation I've outlined above (which
> may be too spread out...), there's no obvious place to put it besides it
> being a new PEP.
> Re base reactor interface: drawing maximally from the lessons learned inThat actually sounds more concrete than I'd like a reactor interface
> twisted, I think IReactorCore (start, stop, etc), IReactorTime (call later,
> etc), asynchronous-looking name lookup, fd handling are the important parts.
to be. In the App Engine world, there is a definite need for a
reactor, but it cannot talk about file descriptors at all -- all I/O
is defined in terms of RPC operations which have their own (several
layers of) async management but still need to be plugged in to user
code that might want to benefit from other reactor functionality such
as scheduling and placing a call at a certain moment in the future.
> call_every can be implemented in terms of call_later on a separate object,This is definitely one of the things we ought to get right. My own
> so I think it should be (eg twisted.internet.task.LoopingCall). One thing
> that is apparently forgotten about is event loop integration. The prime way
> of having two event loops cooperate is *NOT* "run both in parallel", it's
> "have one call the other". Even though not all loops support this, I think
> it's important to get this as part of the interface (raise an exception for
> all I care if it doesn't work).
thoughts are slightly (perhaps only cosmetically) different again:
ideally each event loop would have a primitive operation to tell it to
run for a little while, and then some other code could tie several
event loops together.
Possibly the primitive operation would be something like "block until
either you've got one event ready, or until a certain time (possibly
0) has passed without any events, and then give us the events that are
ready and a lower bound for when you might have more work to do" -- or
maybe instead of returning the event(s) it could just call the
associated callback (it might have to if it is part of a GUI library
that has callbacks written in C/C++ for certain events like screen
refreshes).
Anyway, it would be good to have input from representatives from Wx,
Qt, Twisted and Tornado to ensure that the *functionality* required is
all there (never mind the exact signatures of the APIs needed to
provide all that functionality).
Guido van Rossum <guido@...> writes:
> (2) We're at a fork in the road here. On the one hand, we could choose
> to deeply integrate greenlets/gevents into the standard library.
Yes.
I have two and a half reasons for this.
(½) Ultimately I think that switching stacks around is always going to be faster
than unwinding and re-winding things with yield().
(1) It's a whole lot easier to debug a problem with gevent than with anything
which uses yield / Deferreds / asyncore / whatever. With gevent, you get a
standard stack trace. With anything else, the "where did this call come from"
information is not part of the call chain and thus is either unavailable, or
will have to be carried around preemptively (with associated overhead).
(2) Nothing against Twisted or any other async frameworks, but writing any
nontrivial program in it requires warping my brain into something that's *not*
second nature in Python, and never going to be.
Python is not Javascript; if you want to use the "loads of callbacks"
programming style, use node.js.
Personal experience: I have written an interpreter for an asynchronous and
vaguely Pythonic language which I use for home automation, my lawn sprinkers,
and related stuff (which I should probably release in some form). The code was
previously based on Twisted and was impossible to debug. It now uses gevent and
Just Works.
--
-- Matthias Urlichs
On 16.10.12 20:40, Matthias Urlichs wrote:
> I'll have to put in my ..02€ here …
>
> Guido van Rossum <guido@...> writes:
>
>> (2) We're at a fork in the road here. On the one hand, we could choose
>> to deeply integrate greenlets/gevents into the standard library.
> Yes.
>
> I have two and a half reasons for this.
>
> (½) Ultimately I think that switching stacks around is always going to be faster
> than unwinding and re-winding things with yield().
If you are emulating things in Python, that may be true.
Also if you are really only switching stacks, that may be true.
But both assumptions do not fit, see below.
>
> (1) It's a whole lot easier to debug a problem with gevent than with anything
> which uses yield / Deferreds / asyncore / whatever. With gevent, you get a
> standard stack trace. With anything else, the "where did this call come from"
> information is not part of the call chain and thus is either unavailable, or
> will have to be carried around preemptively (with associated overhead).
I'm absolutely your's on ease of coding straight forward.
But this new, efficient "yield from" is a big step into that direction,
see Greg's reply.
> (2) Nothing against Twisted or any other async frameworks, but writing any
> nontrivial program in it requires warping my brain into something that's *not*
> second nature in Python, and never going to be.
Same here.
> Python is not Javascript; if you want to use the "loads of callbacks"
> programming style, use node.js.
>
>
> Personal experience: I have written an interpreter for an asynchronous and
> vaguely Pythonic language which I use for home automation, my lawn sprinkers,
> and related stuff (which I should probably release in some form). The code was
> previously based on Twisted and was impossible to debug. It now uses gevent and
> Just Works.
You are using gevent, which uses greenlet!
That means no pure stack switching, but the stack is sliced and
moved onto the heap.
But that technique (originally from Stackless 2.0) is known to be
5-10 times slower, compared to a cooperative context switching
that is built into the interpreter.
This story is by far not over.
Even PyPy with all its advanced technology still depends on stack slicing
when it emulates concurrency.
Python 3.3 has done a huge move, because this efficient nesting
of generators can deeply influence how people are coding,
maybe with the effect that stack tricks loose more of their
importance. I expect more like this to come.
Greenlets are great. Stack inversion is faster.
--
Christian Tismer :^) <mailto:tis...@stackless.com>
Software Consulting : Have a break! Take a ride on Python's
Karl-Liebknecht-Str. 121 : *Starship* http://starship.python.net/
14482 Potsdam : PGP key -> http://pgp.uni-mainz.de
phone +49 173 24 18 776 fax +49 (30) 700143-0023
PGP 0x57F3BF04 9064 F4E1 D754 C2FF 1619 305B C09C 5A3B 57F3 BF04
whom do you want to sponsor today? http://www.stackless.com/
_______________________________________________
I'll have to put in my ..02€ here …
Yes.
Guido van Rossum <guido@...> writes:
> (2) We're at a fork in the road here. On the one hand, we could choose
> to deeply integrate greenlets/gevents into the standard library.
I have two and a half reasons for this.
(½) Ultimately I think that switching stacks around is always going to be faster
than unwinding and re-winding things with yield().
(1) It's a whole lot easier to debug a problem with gevent than with anything
which uses yield / Deferreds / asyncore / whatever. With gevent, you get a
standard stack trace. With anything else, the "where did this call come from"
information is not part of the call chain and thus is either unavailable, or
will have to be carried around preemptively (with associated overhead).
(2) Nothing against Twisted or any other async frameworks, but writing any
nontrivial program in it requires warping my brain into something that's *not*
second nature in Python, and never going to be.
Python is not Javascript; if you want to use the "loads of callbacks"
programming style, use node.js.
Personal experience: I have written an interpreter for an asynchronous and
vaguely Pythonic language which I use for home automation, my lawn sprinkers,
and related stuff (which I should probably release in some form). The code was
previously based on Twisted and was impossible to debug. It now uses gevent and
Just Works.
--
-- Matthias Urlichs
_______________________________________________
Python-ideas mailing list
Python...@python.org
http://mail.python.org/mailman/listinfo/python-ideas