[Python-Dev] Obtaining stack-frames from co-routine objects

Ben Leslie benno at benno.id.au
Sun Jun 14 02:00:05 CEST 2015


On 14 June 2015 at 09:20, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
> Nick Coghlan wrote:
>>
>> I wonder if in 3.6 it might be possible to *add* some bookkeeping to
>> "await" and "yield from" expressions that provides external visibility
>> into the underlying iterable or coroutine that the generator-iterator
>> or coroutine has delegated flow control to.
>
>
> In my original implementation of yield-from, stack frames
> had an f_yieldfrom slot referring to the object being
> yielded from.
>
> I gather that slot no longer exists at the C level, but
> it ought to be possible to provide a Python attribute or
> method returning the same information.

OK, this is really easy to implement actually. I implemented it as gi_yieldfrom
on the generator object rather than f_yieldfrom on the frame object,
primarily as most of the related code is already in the genobject.c module.

Something like this:

diff --git a/Objects/genobject.c b/Objects/genobject.c
index 3c32e7b..bc42fe5 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -553,11 +553,22 @@ gen_set_qualname(PyGenObject *op, PyObject *value)
     return 0;
 }

+static PyObject *
+gen_getyieldfrom(PyGenObject *gen)
+{
+    PyObject *yf = gen_yf(gen);
+    if (yf == NULL)
+        Py_RETURN_NONE;
+
+    return yf;
+}
+
 static PyGetSetDef gen_getsetlist[] = {
     {"__name__", (getter)gen_get_name, (setter)gen_set_name,
      PyDoc_STR("name of the generator")},
     {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname,
      PyDoc_STR("qualified name of the generator")},
+    {"gi_yieldfrom", (getter)gen_getyieldfrom, NULL, NULL},
     {NULL} /* Sentinel */
 };

(Note: Above probably doesn't exactly follow correct coding conventions, and
probably need to add an appropriate doc string.)

This greatly simplifies my very original 'show' routine to:

def show(coro):
    print("{}:{} ({})".format(coro.gi_frame.f_code.co_filename,
coro.gi_frame.f_lineno, coro))
    if coro.gi_yieldfrom:
        show(coro.gi_yieldfrom)

I think this would give the widest flexibility for non-CPython
implementations to implement
the same property in the most appropriate manner.

If this seems like a good approach I'll try and work it in to a
suitable patch for contribution.

Cheers,

Ben


More information about the Python-Dev mailing list