I'd like to propose adding the ability for context managers to catch and
handle control passing into and out of them via yield and generator.send()
def __init__(self, path):
self.inner_path = path
self.outer_path = os.getcwd()
def __exit__(self, exc_type, exc_val, exc_tb):
self.inner_path = os.getcwd()
self.outer_path = os.getcwd()
Here __yield__() would be called when control is yielded through the with
block and __send__() would be called when control is returned via .send()
or .next(). To maintain compatibility, it would not be an error to leave
either __yield__ or __send__ undefined.
The rationale for this is that it's sometimes useful for a context manager
to set global or thread-global state as in the example above, but when the
code is used in a generator, the author of the generator needs to make
assumptions about what the calling code is doing. e.g.
Even if the author of this generator knows what effect do_something() and
do_something_else() have on the current working directory, the author needs
to assume that the caller of the generator isn't touching the working
directory. For instance, if someone were to create two my_generator()
generators with different paths and advance them alternately, the resulting
behaviour could be most unexpected. With the proposed change, the context
manager would be able to handle this so that the author of the generator
doesn't need to make these assumptions.
Naturally, nested with blocks would be handled by calling __yield__ from
innermost to outermost and __send__ from outermost to innermost.
I rather suspect that if this change were included, someone could come up
with a variant of the contextlib.contextmanager decorator to simplify
writing generators for this sort of situation.
J. D. Bartlett
I think it would be a good idea if Python tracebacks could be translated
into languages other than English - and it would set a good example.
For example, using French as my default local language, instead of
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
I might get something like
Suivi d'erreur (appel le plus récent en dernier) :
Fichier "<stdin>", à la ligne 1, dans <module>
ZeroDivisionError: division entière ou modulo par zéro
Greg Ewing wrote:
> Mark Shannon wrote:
>> Why not have proper co-routines, instead of hacked-up generators?
> What do you mean by a "proper coroutine"?
A parallel, non-concurrent, thread of execution.
It should be able to transfer control from arbitrary places in
execution, not within generators.
Stackless provides coroutines. Greenlets are also coroutines (I think).
Lua has them, and is implemented in ANSI C, so it can be done portably.
(One of the examples in the paper uses coroutines to implement
generators, which is obviously not required in Python :) )
Here's an updated version of the PEP reflecting my
recent suggestions on how to eliminate 'codef'.
Author: Gregory Ewing <greg.ewing(a)canterbury.ac.nz>
Type: Standards Track
A syntax is proposed for defining and calling a special type of generator
called a 'cofunction'. It is designed to provide a streamlined way of
writing generator-based coroutines, and allow the early detection of
certain kinds of error that are easily made when writing such code, which
otherwise tend to cause hard-to-diagnose symptoms.
This proposal builds on the 'yield from' mechanism described in PEP 380,
and describes some of the semantics of cofunctions in terms of it. However,
it would be possible to define and implement cofunctions independently of
PEP 380 if so desired.
A cofunction is a special kind of generator, distinguished by the presence
of the keyword ``cocall`` (defined below) at least once in its body. It may
also contain ``yield`` and/or ``yield from`` expressions, which behave as
they do in other generators.
From the outside, the distinguishing feature of a cofunction is that it cannot
be called the same way as an ordinary function. An exception is raised if an
ordinary call to a cofunction is attempted.
Calls from one cofunction to another are made by marking the call with
a new keyword ``cocall``. The expression
cocall f(*args, **kwds)
is evaluated by first checking whether the object ``f`` implements
a ``__cocall__`` method. If it does, the cocall expression is
yield from f.__cocall__(*args, **kwds)
except that the object returned by __cocall__ is expected to be an
iterator, so the step of calling iter() on it is skipped.
If ``f`` does not have a ``__cocall__`` method, or the ``__cocall__``
method returns ``NotImplemented``, then the cocall expression is
treated as an ordinary call, and the ``__call__`` method of ``f``
Objects which implement __cocall__ are expected to return an object
obeying the iterator protocol. Cofunctions respond to __cocall__ the
same way as ordinary generator functions respond to __call__, i.e. by
returning a generator-iterator.
Certain objects that wrap other callable objects, notably bound methods,
will be given __cocall__ implementations that delegate to the underlying
The full syntax of a cocall expression is described by the following
atom: cocall | <existing alternatives for atom>
cocall: 'cocall' atom cotrailer* '(' [arglist] ')'
cotrailer: '[' subscriptlist ']' | '.' NAME
Note that this syntax allows cocalls to methods and elements of sequences
or mappings to be expressed naturally. For example, the following are valid:
y = cocall self.foo(x)
y = cocall funcdict[key](x)
y = cocall a.b.c[i].d(x)
Also note that the final calling parentheses are mandatory, so that for example
the following is invalid syntax:
y = cocall f # INVALID
New builtins, attributes and C API functions
To facilitate interfacing cofunctions with non-coroutine code, there will
be a built-in function ``costart`` whose definition is equivalent to
def costart(obj, *args, **kwds):
m = obj.__cocall__
result = NotImplemented
result = m(*args, **kwds)
if result is NotImplemented:
raise TypeError("Object does not support cocall")
There will also be a corresponding C API function
PyObject *PyObject_CoCall(PyObject *obj, PyObject *args, PyObject *kwds)
It is left unspecified for now whether a cofunction is a distinct type
of object or, like a generator function, is simply a specially-marked
function instance. If the latter, a read-only boolean attribute
``__iscofunction__`` should be provided to allow testing whether a given
function object is a cofunction.
Motivation and Rationale
The ``yield from`` syntax is reasonably self-explanatory when used for the
purpose of delegating part of the work of a generator to another function. It
can also be used to good effect in the implementation of generator-based
coroutines, but it reads somewhat awkwardly when used for that purpose, and
tends to obscure the true intent of the code.
Furthermore, using generators as coroutines is somewhat error-prone. If one
forgets to use ``yield from`` when it should have been used, or uses it when it
shouldn't have, the symptoms that result can be extremely obscure and confusing.
Finally, sometimes there is a need for a function to be a coroutine even though
it does not yield anything, and in these cases it is necessary to resort to
kludges such as ``if 0: yield`` to force it to be a generator.
The ``cocall`` construct address the first issue by making the syntax directly
reflect the intent, that is, that the function being called forms part of a
The second issue is addressed by making it impossible to mix coroutine and
non-coroutine code in ways that don't make sense. If the rules are violated, an
exception is raised that points out exactly what and where the problem is.
Lastly, the need for dummy yields is eliminated by making it possible for a
cofunction to call both cofunctions and ordinary functions with the same syntax,
so that an ordinary function can be used in place of a cofunction that yields
Record of Discussion
An earlier version of this proposal required a special keyword ``codef`` to be
used in place of ``def`` when defining a cofunction, and disallowed calling an
ordinary function using ``cocall``. However, it became evident that these
features were not necessary, and the ``codef`` keyword was dropped in the
interests of minimising the number of new keywords required.
The use of a decorator instead of ``codef`` was also suggested, but the current
proposal makes this unnecessary as well.
It has been questioned whether some combination of decorators and functions
could be used instead of a dedicated ``cocall`` syntax. While this might be
possible, to achieve equivalent error-detecting power it would be necessary
to write cofunction calls as something like
yield from cocall(f)(args)
making them even more verbose and inelegant than an unadorned ``yield from``.
It is also not clear whether it is possible to achieve all of the benefits of
the cocall syntax using this kind of approach.
An implementation of an earlier version of this proposal in the form of patches
to Python 3.1.2 can be found here:
If this version of the proposal is received favourably, the implementation will
be updated to match.
This document has been placed in the public domain.
Yury Selivanov wrote:
> On 2012-03-16, at 2:57 PM, Yury Selivanov wrote:
>> Decorators can be nested, and what you can do in this case is to
>> find the most inner-wrapped function by traversing the '__wrapped__'
>> attributes (and check that the function you found is the actual
>> original function). After that you can play with its attributes,
>> but you can't simply substitute the function object, as the inner
>> decorator won't use it. So sometimes you have to work with the
>> function object without a way of substituting it.
> And that applies to the situations where decorators are not enough
> and you have to work on the opcode level.
Which you can do with a decorator.
Would this do what you want?
def f_with_new_closure(f, closure):
I propose to add Thread.interrupt() function.
th.interrupt() will set a flag in ThreadState structure.
When interpreter switches to next thread it will check that flag.
If flag is on then ThreadInterruptionError will be raised in thread context.
If thread has blocked via threading locks (Lock, RLock, Condition,
Semaphore etc) — exception is raised also.
Of course we cannot interrupt thread if it has been locked by C
Extension call or just waiting for blocking IO.
But, I think, the way to force stopping of some thread can be useful
and has no incompatibility effect.
The standard way to stop thread is the sending some message which is
the signal to thread for termination.
Pushing None or sentinel into thread message queue for example.
— check 'interrupted' state explicitly by call
threading.current_thread().interrupted() than do what you want.
— do the same as boost.threading does: check state in direct
interruption point and locks if interruption is enabled.
BTW, we can disable interruption mechanic by default and use it only
if switched on by threading.enable_interruption()
What do you think?
Given that for some time the try/except/else form is standard and
encouraged, I've found the following pattern really common in my code:
r = some_single_statement()
print "oh no!"
p = prepare(r)
print "I got", p
Where the try block ever doing more than one thing feels dangerous or sloppy,
because I want to make sure I know exactly where the exception comes from.
The else block becomes the long tail and the try is just the head. This makes
the try block itself seem heavy.
What if we allowed this to be implied and except/else blocks bound to
statement? A try block would be an optional form, and mostly left for
r = some_single_statement()
print "oh no!"
p = prepare(r)
print "I got", p
I think it reads acceptably. With a try: block your eye leads up right
to that one statement.
There is no ambiguity to deal with, that I can tell. I'm not sure if
this is a great idea,
but I don't dislike it.
Read my blog! I depend on your acceptance of my opinion! I am interesting!
Follow me if you're into that sort of thing: http://www.twitter.com/ironfroggy
(reposting this from Google Group once more as the previous post missed
Mailing List, because I was not subscribed in Mailman)
*Static module/package inspection*
- static: without execution (as opposed to dynamic)
- module/package: .py or __init__.py file
- inspection: get an overview of the contents
*What should this do?*
The proposal to add a mechanism to Python interpreter to get an outline of
module/package contents without importing or executing module/package. The
outline includes names of classes, functions, variables. It also should
contain values for variables that could be provided without sophisticated
calculations (e.g. a string, integer, but probably not expressions as it
may lead to security leaks).
*user story PEPx.001:*
As a Python package maintainer, I find it bothersome to repeatedly write
bolierplate code (e.g. setup.py) to package my single file module. The
reason I should write setup.py is to provide version and description info.
This info is already available in my module source code. So I need to
either copy/paste the info from the module manually, or to import (and
hence execute) my module during packaging and installation, which I don't
want either, because modules are often installed with root privileges.
With this PEP, packing tool will be able to extract meta information from
my module without executing it or without me manually copying version
fields into some 'package configuration file'.
*user story PEPx.002:*
As a Python Application developer, I find it really complicated to provide
plugin extension subsystem for my users. Users need a mechanism to switch
between different versions of the plugin, and this mechanism is usually
provided by external tool such as setuptools to manage and install multiple
versions of plugins in local Python package repository. It is rather hard
to create an alternative approach, because you are forced to maintain
external meta-data about your plugin modules even in case it is already
available inside the module.
With this PEP, Python Application will be able to inspect
meta-data embedded inside of plugins before choosing which version to load.
This will also provide a standard mechanism for applications to check
modules returned by packaging tools without executing them. This will
greatly simplify writing and debugging custom plugins loaders on different
At this stage I'd like to a community response to two separate questions:
1. If everybody feels this functionality will be useful for Python
2. If the solution is technically feasible
Can we make the __closure__ attribute writeable? Since __code__ already is,
and it is possible to tackle with the opcodes, having no way of rewriting
__closure__ (except creating a completely new function) is annoying.
I don't think it will somehow harm python, as those who want to break it can
do it already in multiple ways, easier than playing with __closure__.