首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将不同的python包放入相同的命名空间?

将不同的python包放入相同的命名空间?
EN

Stack Overflow用户
提问于 2009-01-18 05:17:19
回答 5查看 8.8K关注 0票数 19

我正在开发一个python框架,它将把“插件”写成单独的包。即:

代码语言:javascript
运行
复制
import myframework
from myframework.addons import foo, bar

现在,我试图安排的是,这些插件可以独立于核心框架分发,并注入到myframework.addons命名空间中。

目前,我对此的最佳解决方案如下。将部署一个附加组件(最有可能部署到{python_version}/site-packages/中,如下所示:

代码语言:javascript
运行
复制
fooext/
fooext/__init__.py
fooext/myframework/
fooext/myframework/__init__.py
fooext/myframework/addons/
fooext/myframework/addons/__init__.py
fooext/myframework/addons/foo.py

fooext/myframework/addons/__init__.py将具有pkgutil路径扩展代码:

代码语言:javascript
运行
复制
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)

问题是,为了让它工作,PYTHONPATH中需要有fooext/,但是它唯一需要的是父安装目录(最有可能是上面提到的site-packages)。

这个问题的解决方案是在myframework/addons/__init__.py中有额外的代码,它将遍历sys.path并查找任何带有MyFramework子程序包的模块,在这种情况下,它会将其添加到sys.path中,一切都会正常工作。

我的另一个想法是将插件文件直接写入myframework/addons/安装位置,但这样做会使开发和部署的命名空间不同。

有没有更好的方法来实现这一点,或者也许有一种完全不同的方法来解决上面的分布问题?

EN

Stack Overflow用户

回答已采纳

发布于 2009-01-18 15:01:31

有没有更好的方法来实现这一点,或者可能有一种完全不同的方法来解决上面的分发问题?

有可能。Python的模块/包设置通常很难像这样动态地进行篡改,但是它的对象/类系统是开放的,并且可以以定义良好的方式进行扩展。当模块和包没有很好地封装项目所需的功能时,您可以使用类来代替。

例如,您可以将扩展功能放在一个完全不同的包中,但允许它通过特定接口将类注入到您的基本框架中。例如:包含基本应用程序包装器的myframework/_​​_​init​_​​_.py:

代码语言:javascript
运行
复制
class MyFramework(object):
    """A bare MyFramework, I only hold a person's name
    """
    _addons= {}
    @staticmethod
    def addAddon(name, addon):
        MyFramework._addons[name]= addon

    def __init__(self, person):
        self.person= person
        for name, addon in MyFramework._addons.items():
            setattr(self, name, addon(self))

然后,您可以在myexts/helloer.py中拥有扩展功能,它保留对其“所有者”或“外部”MyFramework类实例的引用:

代码语言:javascript
运行
复制
class Helloer(object):
    def __init__(self, owner):
        self.owner= owner
    def hello(self):
        print 'hello '+self.owner.person

import myframework
myframework.MyFramework.addAddon('helloer', Helloer)

所以现在如果你只是“导入myframework",你只能得到基本的功能。但是,如果您还“导入myexts.helloer”,您还可以调用MyFramework.helloer.hello()。当然,您也可以为插件定义协议,以与基本框架行为进行交互,并相互进行交互。如果你需要这样的复杂性,你也可以做一些事情,比如框架的子类可以覆盖内部类来进行定制,而不必修补可能会影响其他应用程序的类。

封装这样的行为可能很有用,但为了适应这个模型,调整模块级代码通常是一项烦人的工作。

票数 4
EN
查看全部 5 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/454691

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档