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模块)是简单性,我确实打算在插件编写不正确的情况下实现一个回退。(在这种情况下,它只需导入插件并丢弃或轻轻打印它可能返回的任何异常)在进一步测试之后:爱它。工作完美。谢谢