Прямой доступ к классам из произвольных модулей внутри пакета - PullRequest
3 голосов
/ 04 марта 2012

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

Например:

  • / Настройки /
  • / Настройки / __init__.py
  • / Настройки / AbstractSetting.py
  • / Настройки / Float.py
  • / Settings / String.py

Каждый класс внутри каждого модуля имеет то же имя, что и модуль, и в настоящее время я продолжаю делать это:

import Settings
mysetting = Settings.Float.Float()

..дает мне эти двойные имена «Float».

Я мог бы сделать, в __init__.py пакета:

from Float import Float

.. так, чтобы я мог тогда сделать:

import Settings
mysetting = Settings.Float()

Но я бы хотел, чтобы этот пакет динамически обновлялся до любых модулей, которые я вставил в него.Чтобы на следующий день, когда я добавил «Knob.py» в этот пакет, я мог сделать:

import Settings
myknob = Settings.Knob()

Имеет смысл?

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

Может быть, пакеты - это не тот путь?Какие у меня есть альтернативы?

Спасибо большое.

РЕДАКТИРОВАТЬ: Основная причина, по которой я хочу это сделать, - позволить пользователям писать свои собственные модули, которые будут интегрироваться с остальной частью приложения.Родная "плагиновая" архитектура, если хотите.

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

Я еще кое-что прочитал, и, видимо, это не тот путь.Хотелось бы услышать ваши идеи о том, какими могут быть преимущества / недостатки этого подхода.

Ответы [ 2 ]

3 голосов
/ 04 марта 2012

Вы должны знать, что это не путь Python. «Один класс на файл» - это философия Java, которая не применяется в мире Python. Мы обычно называем модули в нижнем регистре и вставляем связанные классы в один и тот же файл (в вашем примере все классы помещаются в settings.py или будут явно импортированы оттуда). Но я думаю, тот факт, что вы хотите, чтобы пользователи предоставляли плагины, является законной причиной вашего подхода (я думаю, что immdbg делает то же самое).

Итак, если вы действительно хотите это сделать, вы можете поместить что-то вроде этого в свой Settings/__init__.py:

import os
import glob
import imp

for f in glob.glob(os.path.join(os.path.dirname(__file__), '*.py')):
  modname = os.path.basename(f)[:-3]
  if modname.startswith('__'): continue
  mod = imp.load_source(modname, f)

  globals()[modname] = getattr(mod, modname)

  # or if you just want to import everything (even worse):
  #for name in dir(mod):
  #  if name.startswith('__'): continue
  #  globals()[name] = getattr(mod, name)

Можете ли вы почувствовать, как разработчики Python не хотят, чтобы вы это делали? :)

2 голосов
/ 04 марта 2012

Существует множество плагинов. Это подтверждается названием одной такой системы yapsy (еще одна система плагинов).

Вы можете создать объект, обеспечивающий необходимый интерфейс:

class Settings(object):
    def __getattr__(self, attr):
        return load_plugin(attr)

settings = Settings()

В вашем коде:

from settings import settings

knob = settings.Knob()

Вы можете использовать любую реализацию, какую пожелаете для load_plugin(), например, для кода из вопроса:

from importlib import import_module

def load_plugin(name):
    m = import_module('Settings.'+name)
    return getattr(m, name)
...