Проверить наличие переменной в классе в отдельном файле, не зная имени класса? - PullRequest
1 голос
/ 20 сентября 2019

Мне известно о hasattr(), но я не думаю, что это подойдет для моих конкретных потребностей.Вот ситуация.

В настоящее время у меня есть возможность проверить каталог для классов с определенным типом.IE class TabFrame(ttk.Frame) будет загружен, поскольку он наследуется именно от ttk.Frame.

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

Основная проблема заключается в том, что у меня нет возможности узнать все имена классов в файлах в каталоге.Мое текущее решение создает кнопки для каждого файла в каталоге, а не для конкретного класса, который я хочу загрузить.

Мой файл, который создает все кнопки на основе имен файлов в каталоге, которые соответствуют моим критериям для допустимых имен файлов.

Итак, проблема в том, что вместо кнопок, которые создаются для каждого допустимого имени файла, мне действительно нужно создать кнопки для каждого допустимого класса в каждом допустимом имени файла.Я подумал, что мог бы использовать простой атрибут класса, такой как self.valid_class = True, в качестве контроля для того, что загружается в виде кнопки, однако я не знаю, как я могу проверить каждый класс, не импортировав их сначала напрямую.

Пример кода, который вы можетеиспользуйте, чтобы проверить, как это работает:

import tkinter as tk
import tkinter.ttk as ttk
import os
import glob
import importlib.util as iu
from os.path import dirname, basename, isfile, join

file_list = os.listdir('./ScriptFrames')
modules = glob.glob(join(dirname('.\ScriptFrames\\'), "*.py"))
__all__ = [basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]


class ScriptManager(tk.Tk):
    def __init__(self):
        super().__init__()
        self.columnconfigure(0, weight=1)
        self.tab_list = {}
        top_frame = tk.Frame(self)
        bot_frame = tk.Frame(self)
        self.book = ttk.Notebook(bot_frame)
        self.book.pack()
        top_frame.pack()
        bot_frame.pack()
        for ndex, file_name in enumerate([x.split('.')[0] for x in file_list]):
            if not any(substring in file_name for substring in ['__', 'TaskFrame']):
                tk.Button(top_frame, text=file_name, width=30,
                          command=lambda fn=file_name: self.add_tab(fn)).grid(row=ndex, column=0, padx=5, pady=1)

    def add_tab(self, file_name):
        self.process_import(file_name)
        self.add_frame_to_book(self.tab_list[file_name])

    def add_frame_to_book(self, frame_object):
        self.book.add(frame_object, text=frame_object.tab_title)

    def process_import(self, fname=None):
        if fname is not None:
            for fn in __all__:
                if fn == fname:
                    spec = iu.spec_from_file_location('ScriptFrames.{}'.format(fn), '.\ScriptFrames\\{}.py'.format(fn))
                    modlst = iu.module_from_spec(spec)
                    spec.loader.exec_module(modlst)

                    mod_itms = [getattr(modlst, item, None) for item in dir(modlst)]
                    fc = [item for item in mod_itms if isinstance(item, (type,))
                          and issubclass(item, (ttk.Frame, tk.LabelFrame))]

                    self.tab_list[fn] = fc[0]()


if __name__ == '__main__':
    ScriptManager().mainloop()

Базовый класс кадров tkinter, используемый из отдельного файла.находится в папке в главном каталоге с именем ScriptFrames.Имя файла TestFrame3, поэтому кнопка имеет такое имя.

import tkinter as tk
import tkinter.ttk as ttk


class TabFrame(ttk.Frame):
    def __init__(self):
        super().__init__()
        self.valid_tab = "Tab Name" # I want to ID this variable.
        self.tab_title = 'Test Frame 3'
        tk.Label(self, text=self.tab_title).grid(row=0, column=0, sticky='nsew')

Как файлы загружаются как кнопки, а затем как они загружаются в блокнот tkinter.

strong text

Таким образом, все работает так, как задумано, однако я хочу на самом деле проверить каждый класс в файле и посмотреть, есть ли в этом классе переменная, которая сообщитмне, если я должен сделать кнопку, чтобы открыть этот класс в новой вкладке на ноутбуке.

Имейте в виду, я не знаю, сколько файлов или классов находится в этом каталоге, но я хочу сделать кнопку для каждогодопустимый класс в качестве идентификатора в зависимости от того, имеет ли он атрибут класса self.valid_tab.

1 Ответ

0 голосов
/ 21 сентября 2019

Может быть, одним из подходов может быть запуск сценария «регистрации», который записывает файл .ini после каждого нового коммита в папке utils?

Сценарий может проверять каждый класс, анализировать значениявсе классы и их атрибуты в виде набора флагов подписи, что позволяет их различать и записывать в файл конфигурации, возможно, используя configparser.

. Вы можете запустить его вручную, используя инструмент, подобный watchdog, чтобызапускайте ее каждый раз, когда папка изменяется, или задайте задание cron, чтобы запускать ее через определенные промежутки времени.

После запуска графический интерфейс будет считывать (или получать аргумент) последний файл .ini исконфигурируйте себя с помощью соответствующих кнопок.

При таком подходе вам не нужно импортировать какие-либо классы до того, как они понадобятся;вам не нужно проверять классы на лету;вам не нужно беспокоиться, если ваш графический интерфейс отражает последние добавления к utils.Кроме того, все «бесполезные» проверки классов и анализ файла configuration скрыты в скрипте, который запускается только при необходимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...