直接从包内的任意模块访问类

时间:2012-03-04 17:02:39

标签: python oop plugins packages

不确定是否有一种巧妙的处理方式,我可以直观地将每个对象/类放入一个共同包装下的自己的模块中。

例如:

  • /设置/
  • /设置/ __init__.py
  • /设置/ AbstractSetting.py
  • /设置/ Float.py
  • /设置/ 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 个答案:

答案 0 :(得分:3)

你应该知道这不是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开发人员不希望你这样做吗? :)

答案 1 :(得分:2)

有许多插件系统。例如,一个这样的系统的名称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)