Finding closures through introspection

John Nagle nagle at animats.com
Mon Jun 14 23:46:28 EDT 2010


   I'm doing something with CPython introspection, and I'm trying
to determine whether a function is a closure.  Consider

   def foo(x) :
      global fbar
      def bar(y) :
        pass
      fbar = bar # export closure


   foo(0)

We now have "fbar" as a reference to a closure.

"inspect" can tell us some things about foo and fbar:

 >>> inspect.getargspec(foo)
ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
 >>> inspect.getargspec(fbar)
ArgSpec(args=['y'], varargs=None, keywords=None, defaults=None)

No difference there.

 >>> fbar.func_globals
{'fbar': <function bar at 0x021FD470>,
'__builtins__': <module '__builtin__' (built-in)>,
'inspect': <module 'inspect' from 'C:\python26\lib\inspect.pyc'>,
'm':
[('__call__', <method-wrapper '__call__' of function object at 0x021FD470>),
('__class__', <type 'function'>), ('__closure__', None),
('__code__', <code object bar at 021F1C38, file "<stdin>", line 3>),
('__defaults__', None),
('__delattr__', <method-wrapper '__delattr__' of function object at 
0x021FD470>),
('__dict__', {}),
('__doc__', None), ('__format__', <built-in method __format__ of 
function object at 0x021FD470>),
('__get__', <method-wrapper '__get__' of function object at 0x021FD470>),
('__getattribute__', <method-wrapper '__getattribute__' of function 
object at 0x021FD470>),
('__globals__', {...}),
('__hash__', <method-wrapper '__hash__' of function object at 0x021FD470>),
('__init__', <method-wrapper '__init__' of function object at 0x021FD470>),
('__module__', '__main__'),
('__name__', 'bar'),
('__new__', <built-in method __new__ of type object at 0x1E1FACF0>),
('__reduce__', <built-in method __reduce__ of function object at 
0x021FD470>),
('__reduce_ex__', <built-in method __reduce_ex__ of function object at 
0x021FD470>),
('__repr__', <method-wrapper '__repr__' of function object at 0x021FD470>),
('__setattr__', <method-wrapper '__setattr__' of function object at 
0x021FD470>),
('__sizeof__', <built-in method __sizeof__ of function object at 
0x021FD470>),
('__str__', <method-wrapper '__str__' of function object at 0x021FD470>),
('__subclasshook__', <built-in method __subclasshook__ of type object at 
0x1E1FACF0>),
('func_closure', None),
('func_code', <code object bar at 021F1C38, file "<stdin>", line 3>),
('func_defaults', None),
('func_dict', {}),
('func_doc', None),
('func_globals', {...}),
('func_name', 'bar')],
'__package__': None, '__name__': '__main__',
'foo': <function foo at 0x02223C70>,
'__doc__': None}
 >>>

No indication there that "fbar" is a closure inside "foo".  There
are "__closure__" and "__func_closure__" entries in there, but
they are both None.  A non-closure function has the same entries.

So how can I detect a closure?

					John Nagle



More information about the Python-list mailing list