簡體   English   中英

如何使用Python3在目錄中獲取給定類的所有子類?

[英]How to get all subclass of a given class in a directory with Python3?

我想要一個子類對象的列表,而不僅僅是它們的名稱。

我這樣認為:

  • 首先,使用os.walk獲取所有.py文件
  • 然后使用imp模塊導入所有這些文件( <-這執行不好
  • 檢查那些類是否是子類

目錄結構:

├── src
│   ├── __init__.py 
│   └── connector.py
└── test_app
    ├── __init__.py
    └── test.py

connector.py代碼:

import imp


class BaseModel(object):
    """which I wanna check it's subclass"""


class SomeClass(object):
    @classmethod
    def detect_all(cls, app_path=None):
        for path, subdirs, files in os.walk(app_path):
            for name in files:
                file_list.append(os.path.join(path, name)) if name.endswith('.py') and not name.startswith('_') else ''
        for file in file_list:
            imp.load_source(file.split('/')[0], file)
        print(cls.get_all_subclasses(BaseModel))

    @staticmethod
    def get_all_subclasses(cls):
        # argument cls is a target class
        all_subclasses = []

        for subclass in cls.__subclasses__():
            all_subclasses.append(subclass)
            all_subclasses.extend(SomeClass.get_all_subclasses(subclass))

test.py代碼:

import os
import sys
sys.path.append('../')
sys.path.append('../src')

from src.connector import SomeClass, BaseModel

class User(BaseModel):
    pass

b = User()

current_dir = os.path.dirname(os.path.realpath(__file__))

print(SomeClass.detect_all(current_dir))

但是當我運行此文件時,結果始終是循環,最后給了我一個RecursionError: maximum recursion depth exceeded

如何滿足我的需要,或如何解決此代碼。

首先:Python不是Java。 刪除無用的SomeClass類,讓這兩個函數成為模塊中的函數。 這樣做時,請刪除detect_all的無用“ cls”參數。 我在下面的回答假設此更改。

由於缺少初始化file_list = []因此發布的代碼將無法運行。 我認為它在運行時在那里。

我相信無限遞歸如下: test.py調用detect_all(current_dir) current_dir調用os.walk(current_dir) ,它返回'test.py' 然后,它調用imp.load_source('test.py') 然后test.py (重新)調用detect_all(current_dir) 等等。

不推薦使用imp ,而建議使用importlib 當前的imp章節沒有提到load_source ,但是我認為它在加載源代碼之前不會sys.modules添加'test' 普通導入通過首先檢查sys.modules並僅在未向sys.modules添加一個空模塊之后才加載一個尚未存在的模塊來避免無限遞歸。

您應該執行的操作:運行test.py時,代表目錄test_app/ ''會test_app/ sys.path之前。 因此,您可以按模塊名稱在該目錄中導入模塊。 列出模塊名稱的mod_names 當os.walk找到'xyz.py' ,刪除.py擴展名。 在子目錄中遞歸時,請在'subname.' 因此您將獲得正確的點分模塊名稱,如在常規import語句中使用的名稱一樣。 然后將imp循環替換為

    for mod in mod_names:
        importlib.import_module(mod)

我做類似的事情來測試我正在編寫的軟件包中的所有模塊。 我避免使用排除列表(也包含一些其他模塊)進行遞歸。 但是,由於import_module確實將條目添加到sys.modules中,因此不需要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM