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

Python 直接从包内的任意模块访问类,python,oop,plugins,packages,Python,Oop,Plugins,Packages,我不确定是否有一种简洁的方法来处理它,只是在视觉上,将每个对象/类放到它自己的模块中,放在一个公共包下,对我来说是有意义的 例如: /背景/ /设置/\uuuu init\uuuuu.py /设置/AbstractSetting.py /设置/Float.py /设置/String.py 每个模块中的每个类都与模块同名,目前我一直在这样做: import Settings mysetting = Settings.Float.Float() …这给了我两个“浮动”的名字 我可以在包的\uu

我不确定是否有一种简洁的方法来处理它,只是在视觉上,将每个对象/类放到它自己的模块中,放在一个公共包下,对我来说是有意义的

例如:

  • /背景/
  • /设置/
    \uuuu init\uuuuu.py
  • /设置/
    AbstractSetting.py
  • /设置/
    Float.py
  • /设置/
    String.py
每个模块中的每个类都与模块同名,目前我一直在这样做:

import Settings
mysetting = Settings.Float.Float()
…这给了我两个“浮动”的名字

我可以在包的
\uuuu init\uuuu.py
中执行以下操作:

from Float import Float
…这样我就可以:

import Settings
mysetting = Settings.Float()
但是我希望这个包能够动态地更新到我放在里面的任何模块。所以第二天,当我将“Knob.py”添加到这个包中时,我可以做:

import Settings
myknob = Settings.Knob()
有道理吗

不过,我以前从未使用过软件包,现在仍在努力让它变得尽可能简单。在这一点上,我发现将所有类放在一个越来越麻烦的大主模块中更容易

也许包裹不是最好的选择?我有什么选择

非常感谢

编辑:我想这样做的主要原因是让用户编写自己的模块,与应用程序的其余部分集成。一个本地的“插件”架构,如果你愿意的话

每个模块将包含一个由具有默认值的超类继承的类。然后,应用程序会有一个包含可用模块的浏览器,单击该浏览器时,会显示在模块属性下找到的相关信息。然后,包含的每个类都有一个应用程序可以使用的类似接口


我做了一些进一步的阅读,显然这不是我要走的路。我很想听听您对这种方法的优缺点的看法。

您应该知道,这不是Python的方式。“每个文件一个类”是一种不适用于Python世界的Java哲学。我们通常用小写字母命名模块,并将相关类粘贴到同一个文件中(在您的示例中,所有类都将进入
settings.py
或从那里显式导入)。但我想,您希望用户提供插件这一事实是您采用这种方法的正当理由(我认为immdbg也是这样做的)

所以,如果你真的想这样做,你可以在你的
设置中加入类似的内容

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开发人员不希望你这么做吗?:)

有很多插件系统。例如,一个这样的系统的名称
yapsy
(另一个插件系统)

您可以创建一个提供必要接口的对象:

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

settings = Settings()
在代码中:

from settings import settings

knob = settings.Knob()
您可以为
load\u plugin()
使用您喜欢的任何实现,例如,问题中的代码:

from importlib import import_module

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

我觉得这是实现动态“插件”模块体系结构的合理方法。我完全明白这是非传统的,当我第一次尝试它时,它确实感觉有点错误。:)谢谢你让我知道,我会仔细考虑一下这个方法。FWIW,这个方法可以扩展到允许在模块内部导入任意内容,使用你的包的
\uuuuu init\uuuuuuuuy.py
文件中稍微复杂的代码,请看另一个问题。@martineau:这不是我在回答中故意注释掉的部分吗?@NiklasB:我想,但它突出了一个事实,即包的用户不仅限于从包导入中执行
*
+1似乎非常“Pythonic”,就像在简单、灵活和可扩展中一样。这似乎是应该走的路。这个应用程序的关键(它实际上只是批处理一堆用户创建的python模块)是简单性,我确实打算在插件编写不正确的情况下实现一个回退。(在这种情况下,它只需导入插件并丢弃或轻轻打印它可能返回的任何异常)在进一步测试之后:爱它。工作完美。谢谢