classification
Title: inspect.getclosurevars returns wrong globals dict
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.6
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Daniel Debrunner, Noitul, eric.smith, nitishch, yselivanov
Priority: normal Keywords:

Created on 2019-04-22 08:49 by Noitul, last changed 2019-10-07 19:07 by Daniel Debrunner.

Messages (6)
msg340645 - (view) Author: Noitul (Noitul) Date: 2019-04-22 08:49
>>> import inspect                      
>>> a = 0                               
>>> b = 1                               
>>> def abc():                          
>>>     return a.b                                                      
>>> print(inspect.getclosurevars(abc))  

ClosureVars(nonlocals={}, globals={'a': 0, 'b': 1}, builtins={}, unbound=set())

Should "'b': 1" be in globals dict?
msg340707 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2019-04-23 09:23
I think this is correct. The documentation says globals is "the function’s module globals". I suggest closing this as not a bug.

https://docs.python.org/3/library/inspect.html#inspect.getclosurevars
msg340708 - (view) Author: Noitul (Noitul) Date: 2019-04-23 09:45
Sorry for the misleading snippet above.

And how about this one:

>>> import inspect                      
>>> a = 0                               
>>> b = 1
>>> c = 2                               
>>> def abc():                          
>>>     return a.b                                                      
>>> print(inspect.getclosurevars(abc))  

ClosureVars(nonlocals={}, globals={'a': 0, 'b': 1}, builtins={}, unbound=set())

If this is not a bug, the "globals" is the "function's module globals", but why 'c' not in the "globals"?
msg340710 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2019-04-23 10:10
That is interesting. See these examples. I'm starting a new interpreter each time:

>>> import inspect
>>> def abc(): pass
...
>>> inspect.getclosurevars(abc)
ClosureVars(nonlocals={}, globals={}, builtins={}, unbound=set())
>>>


>>> import inspect
>>> def abc(): a
...
>>> inspect.getclosurevars(abc)
ClosureVars(nonlocals={}, globals={}, builtins={}, unbound={'a'})
>>>

>>> import inspect
>>> a=0
>>> def abc(): a
...
>>> inspect.getclosurevars(abc)
ClosureVars(nonlocals={}, globals={'a': 0}, builtins={}, unbound=set())
>>>

>>> import inspect
>>> a=0
>>> def abc(): a.b
...
>>> inspect.getclosurevars(abc)
ClosureVars(nonlocals={}, globals={'a': 0}, builtins={}, unbound={'b'})
>>>

>>> import inspect
>>> a=0
>>> b=1
>>> def abc(): a.b
...
>>> inspect.getclosurevars(abc)
ClosureVars(nonlocals={}, globals={'a': 0, 'b': 1}, builtins={}, unbound=set())
>>> 

It's odd.
msg340753 - (view) Author: Noitul (Noitul) Date: 2019-04-24 01:50
Look at this 
https://github.com/python/cpython/blob/3.6/Lib/inspect.py#L1412

We are taking names from func.__code__.co_names, which also contains names of object's attributes we visited. As a result, we may get more names unexpectedly in 'globals', 'builtins', and even 'unbound'.

And this example might be another case of this potentially bug

>>> import inspect
>>> def abc():
...     import os
...     sys = None
... 
>>> inspect.getclosurevars(abc)
ClosureVars(nonlocals={}, globals={}, builtins={}, unbound={'os'})
msg354128 - (view) Author: Daniel Debrunner (Daniel Debrunner) Date: 2019-10-07 19:07
Another case:

model="Hello"
class M(object):
    def __init__(self):
        pass
    def __call__(self):
        print(self.model)

cvs = inspect.getclosurevars(M.__call__)

ClosureVars(nonlocals={}, globals={'model': 'Hello'}, builtins={'print': <built-in function print>}, unbound=set())

Of course self.model does not refer to the global model
M()()
AttributeError: 'M' object has no attribute 'model'
History
Date User Action Args
2019-10-07 19:07:31Daniel Debrunnersetnosy: + Daniel Debrunner
messages: + msg354128
2019-04-24 01:50:24Noitulsetmessages: + msg340753
2019-04-23 10:10:33eric.smithsetmessages: + msg340710
2019-04-23 09:45:03Noitulsetstatus: pending -> open

messages: + msg340708
2019-04-23 09:23:47eric.smithsetstatus: open -> pending

nosy: + eric.smith
messages: + msg340707

type: behavior
2019-04-23 03:12:37nitishchsetnosy: + nitishch
2019-04-22 08:55:07xtreaksetnosy: + yselivanov
2019-04-22 08:49:29Noitulcreate