[Python-ideas] make __closure__ writable

Yury Selivanov yselivanov.ml at gmail.com
Fri Mar 23 16:33:42 CET 2012

On 2012-03-23, at 2:19 AM, Eric Snow wrote:
> Couldn't something like the following work?
> def modifier(func):
>    """Traverse the decorator "stack" and patch the bottom-most
> wrapped function."""
>    # relies on __wrapped__ being set at each level of the decorator
> stack and on the
>    # wrapped function being bound in func.__closure__.
>    if not hasattr(func, "__wrapped__"):
>        # patch func.__code__ and func.__closure__
>        code = ...
>        closure = ...
>    else:
>        code = func.__code__
>        closure = list(func.__closure__)
>        closure[closure.index(func.__wrapped__)] = modifier(func.__wrapped__)
>    return type(func)(code, func.__globals__, func.__name__,
> func.__defaults__, tuple(closure))

Well, it certainly possible to hack on this level too, but I wouldn't do
that ;)  The only case I came up with after looking at your code was a
way of extracting the decorated function if the decorator didn't set
__wrapped__ attribute.  But even that is just an idea.

> Also, I'm guessing that your actual use-case looks more like the following:
>    from some_third_party_module import foo
>    #assert foo.__wrapped__ == foo.__closure__[0]
>    foo = modifier(foo)  # hacks up foo.__wrapped__

I described our exact use case here: 

> Hacking the innards of an existing function object is touchy stuff,
> probably the riskiest kind of monkey-patching.  You're basically
> taking the chance of breaking (in ugly, unexpected ways) other code
> that uses that function you just hacked.  Still, there are certainly
> valid use-cases (and we're all consenting adults here).

You're right.  Once you start to work on that level you are on your
own.  But if you really forced to decide between the following three

- introduce some really ugly syntax to support normal try..finally
semantics in coroutine
- patch cpython and restrict your framework from ever being used
by anyone, and introduce additional hassles over deployment
- work with python __code__ object to get around the problem

I vote for the last option.

If you have good unittests you shouldn't experience any problems, 
at least between python major releases.

> However, I'd hate for projects to start getting blamed for
> difficult-to-debug problems that are the result of some other project
> that did this sort of hack.  It's nice when your expectations for a
> function's behavior (or any code for that matter) can remain stable,
> regardless of what libraries are installed along-side.

Well, that's much more complicated problem.  I don't think that
making __closure__ writable will anyhow make it worse.  Once again,
you can screw up the __code__ object even now ;)


More information about the Python-ideas mailing list