Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Python, how do I get the list of classes defined within a particular file?

If a file myfile.py contains:

class A(object):
  # Some implementation

class B (object):
  # Some implementation

How can I define a method so that, given myfile.py, it returns [A, B]?

Here, the returned values for A and B can be either the name of the classes or the type of the classes.

(i.e. type(A) = type(str) or type(A) = type(type))

like image 915
Eric McLachlan Avatar asked Mar 08 '19 16:03

Eric McLachlan


People also ask

How do you access the class list in Python?

Method 1: To get the list of all the attributes, methods along with some inherited magic methods of a class, we use a built-in called dir() . Method 2: Another way of finding a list of attributes is by using the module inspect .

Can you have a list of classes in Python?

Python list can hold a list of class objects. We can create one empty list and append multiple class objects to this list. Each list element will be an object, and we can access any member of that object like method, variables, etc. Note that you can append different class objects to the same list.

Are Python classes in separate files?

No, you can define multiple classes (and functions, etc.) in a single file. A file is also called a module. To use the classes/functions defined in the module/file, you will need to import the module/file.

How many classes can be defined in a Python file?

There is no limit on how many classes one can put in a file or a module.


3 Answers

You can get both:

import importlib, inspect
for name, cls in inspect.getmembers(importlib.import_module("myfile"), inspect.isclass):

you may additionally want to check:

if cls.__module__ == 'myfile'
like image 142
panda-34 Avatar answered Oct 09 '22 11:10

panda-34


In case it helps someone else. Here is the final solution that I used. This method returns all classes defined in a particular package.

I keep all of the subclasses of X in a particular folder (package) and then, using this method, I can load all the subclasses of X, even if they haven't been imported yet. (If they haven't been imported yet, they cannot be accessible via __all__; otherwise things would have been much easier).

import importlib, os, inspect

def get_modules_in_package(package_name: str):
    files = os.listdir(package_name)
    for file in files:
        if file not in ['__init__.py', '__pycache__']:
            if file[-3:] != '.py':
                continue

            file_name = file[:-3]
            module_name = package_name + '.' + file_name
            for name, cls in inspect.getmembers(importlib.import_module(module_name), inspect.isclass):
                if cls.__module__ == module_name:
                    yield cls
like image 35
Eric McLachlan Avatar answered Oct 09 '22 13:10

Eric McLachlan


It's a bit long-winded, but you first need to load the file as a module, then inspect its methods to see which are classes:

import inspect
import importlib.util

# Load the module from file
spec = importlib.util.spec_from_file_location("foo", "foo.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)

# Return a list of all attributes of foo which are classes
[x for x in dir(foo) if inspect.isclass(getattr(foo, x))]
like image 21
match Avatar answered Oct 09 '22 12:10

match