Two curious errors when function globals are manipulated

Steven D'Aprano steve at pearwood.info
Tue Jul 5 11:50:07 EDT 2016


On Wed, 6 Jul 2016 01:27 am, eryk sun wrote:

> On Tue, Jul 5, 2016 at 2:46 PM, Steven D'Aprano <steve at pearwood.info>
> wrote:
>> I've come across two curious behaviours of a function using custom
>> globals. In both cases, I have a function where __globals__ is set to a
>> ChainMap.
> 
> ChainMap implements the MutableMapping abstract base class. But
> CPython needs globals to be a dict. In the current implementation,
> LOAD_GLOBAL calls _PyDict_LoadGlobal, and STORE_GLOBAL calls
> PyDict_SetItem. They don't fall back on the abstract object APIs.

Which is why I use ChainDict, a subclass of ChainMap and dict. It's enough
to allow the FunctionType constructor to accept the argument, and the
assignment *appears* to take place.

If PyDict_SetItem expects an actual dict (accept no substitutes or
subclasses), why is there no error? I would have expected a segfault at
worst or at least an exception.

It works with exec:

py> from collections import ChainMap
py> class ChainDict(ChainMap, dict):
...     pass
...
py> m = ChainDict()
py> exec("x = 1", m, m)
py> m['x']
1

(Tested in both 3.3 and 3.6.)





-- 
Steven
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list