В Python, как я могу получить список классов, определенных в определенном файле? - PullRequest
0 голосов
/ 08 марта 2019

Если файл myfile.py содержит:

class A(object):
  # Some implementation

class B (object):
  # Some implementation

Как определить метод так, чтобы при заданном myfile.py он возвращал [A, B]?

Здесь,возвращаемые значения для A и B могут быть либо именем классов, либо типом классов.

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

Ответы [ 3 ]

2 голосов
/ 08 марта 2019

Вы можете получить оба:

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

, которые вы можете дополнительно проверить:

if cls.__module__ == 'myfile'
2 голосов
/ 08 марта 2019

Это немного затянуто, но сначала вам нужно загрузить файл как модуль, а затем проверить его методы, чтобы увидеть, какие классы:

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))]
0 голосов
/ 08 марта 2019

В случае, если это поможет кому-то еще.Вот окончательное решение, которое я использовал.Этот метод возвращает все классы, определенные в определенном пакете.

Я храню все подклассы X в определенной папке (пакете), а затем, используя этот метод, могу загрузить все подклассы X, даже если они еще не были импортированы.(Если они еще не были импортированы, они не могут быть доступны через __all__; в противном случае все было бы намного проще).

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
...