52

I've already seen the following question but it doesn't quite get me where I want: How can I get a list of all classes within current module in Python?

In particular, I do not want classes that are imported, e.g. if I had the following module:

from my.namespace import MyBaseClass
from somewhere.else import SomeOtherClass

class NewClass(MyBaseClass):
    pass

class AnotherClass(MyBaseClass):
    pass

class YetAnotherClass(MyBaseClass):
    pass

If I use clsmembers = inspect.getmembers(sys.modules[__name__], inspect.isclass) like the accepted answer in the linked question suggests, it would return MyBaseClass and SomeOtherClass in addition to the 3 defined in this module.

How can I get only NewClass, AnotherClass and YetAnotherClass?

Community
  • 1
  • 1
Davy8
  • 30,868
  • 25
  • 115
  • 173
  • 2
    Unless I understand wrong, do the comments to the accepted answer in that question not answer your question? (I did not try it to see if it works though) – zxt Apr 02 '11 at 01:57
  • @zxt d'oh glazed over the comments. You're right, it does answer my question. – Davy8 Apr 02 '11 at 02:47

6 Answers6

28

Inspect the __module__ attribute of the class to find out which module it was defined in.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 6
    A list comprehension along the lines of `[m for m in clsmembers if m[1].__module__ == 'mymodule']` should do the trick. You could also supply a lambda function as the predicate to the `inspect.getmembers()` call, as shown in the question you referred to. – Blair Apr 02 '11 at 02:03
13

I apologize for answering such an old question, but I didn't feel comfortable using the inspect module for this solution. I read somewhere that is wasn't safe to use in production.

Initialize all the classes in a module into nameless objects in a list

See Antonis Christofides comment to answer 1.

I got the answer for testing if an object is a class from How to check whether a variable is a class or not?

So this is my inspect-free solution

def classesinmodule(module):
    md = module.__dict__
    return [
        md[c] for c in md if (
            isinstance(md[c], type) and md[c].__module__ == module.__name__
        )
    ]

classesinmodule(modulename)
Community
  • 1
  • 1
piRSquared
  • 285,575
  • 57
  • 475
  • 624
  • Always iterate over items if you need both: `v for c,v in md.iteritems() if ( isinstance(v, type) and v.__module__ == module.__name__ )` – Mr_and_Mrs_D Jun 04 '16 at 14:39
11

You may also want to consider using the "Python class browser" module in the standard library: http://docs.python.org/library/pyclbr.html

Since it doesn't actually execute the module in question (it does naive source inspection instead) there are some specific techniques it doesn't quite understand correctly, but for all "normal" class definitions, it will describe them accurately.

ncoghlan
  • 40,168
  • 10
  • 71
  • 80
10

I used the below:

# Predicate to make sure the classes only come from the module in question
def pred(c):
    return inspect.isclass(c) and c.__module__ == pred.__module__
# fetch all members of module __name__ matching 'pred'
classes = inspect.getmembers(sys.modules[__name__], pred)

I didn't want to type the current module name in

rmc
  • 101
  • 1
  • 2
2
from pyclbr import readmodule

clsmembers = readmodule(__name__).items()
drruggeri
  • 410
  • 3
  • 6
  • 2
    Although this code might solve the problem, it always good to add an explanation to it. – BDL Jan 19 '17 at 13:13
0

The Keep it simple solution:

> python.exe -c "import unittest"
> python.exe -c "from .panda_tools import *"

Command line help: -c cmd : program passed in as string (terminates option list)

If Python will attempt to loading, if not found gives these error types:

ModuleNotFoundError: No module named 'unittest'
ImportError: attempted relative import with no known parent package
dank8
  • 361
  • 4
  • 20