-2

This is related to a SO question, the solution to which gives me the error noted.

How can I get a list of all classes within current module in Python?

Using the green-checked code from that SO answer, I want to get a list of all class names in my own module, locations.py:

import locations

def print_classes():
    for name, obj in inspect.getmembers(locations.modules[__name__]):
        if inspect.isclass(obj):
            print obj

print_classes()

When I run this, I get AttributeError: 'module' object has no attribute 'modules'

I have tested locations.py -- it contains 31 skeleton classes; it throws no errors.

Community
  • 1
  • 1
macloo
  • 627
  • 1
  • 9
  • 19

3 Answers3

4

The accepted answer uses sys.modules, not locations.modules:

for name, obj in inspect.getmembers(sys.modules[__name__]):

sys.modules is the Python dictionary holding all imported module objects:

This is a dictionary that maps module names to modules which have already been loaded. This can be manipulated to force reloading of modules and other tricks. Note that removing a module from this dictionary is not the same as calling reload() on the corresponding module object.

In your case, you don't need sys.modules, you already have a reference to the module object. You just imported it, so just use it directly:

for name, obj in inspect.getmembers(locations):
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • does sys.modules give class name ? – James Sapam Feb 06 '14 at 16:35
  • @yopy: `sys.modules` is a dictionary. It has keys and values, keys being the module name, the values being the module objects. Module objects have attributes; these are the objects defined in that module. If one of those attributes is a class, then **that class** will have a name. – Martijn Pieters Feb 06 '14 at 16:40
  • Thank you -- this does what I want: `def print_classes(): for name, obj in inspect.getmembers(locations): if inspect.isclass(obj): print name` – macloo Feb 06 '14 at 17:55
0

You can fix that by changing to sys.modules['locations'] or locations:

NB: if you are testing from the same module itself, than you can use : sys.modules[__name__]

>>> import locations
>>> sys.modules['locations']
<module 'locations' from 'locations.pyc'>
>>> locations
<module 'locations' from 'locations.pyc'>
>>>

Here is my locations.py module

class A(object): pass
class B(object): pass
class C(object): pass
class D(object): pass

And here is my testing.py script:

import locations
import inspect

def print_classes():
    for name, obj in inspect.getmembers(locations):
        if inspect.isclass(obj):
            print obj

print_classes()

Output:

<class 'locations.A'>
<class 'locations.B'>
<class 'locations.C'>
<class 'locations.D'>
James Sapam
  • 16,036
  • 12
  • 50
  • 73
0

You might prefer a list comprehension, since the loop is quite small.

from __future__ import print_function
from inspect import getmembers, isclass
import my_module

[print(obj) for obj in getmembers(my_module) if isclass(obj)]
Mike Selik
  • 88
  • 5