将单独的python包放入相同的名称空间? [英] Putting separate python packages into same namespace?

查看:71
本文介绍了将单独的python包放入相同的名称空间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个python框架,该框架将附件"编写为单独的程序包.即:

I'm developing a python framework that would have "addons" written as separate packages. I.e.:

import myframework
from myframework.addons import foo, bar

现在,我要安排的是使这些附加组件可以与核心框架分开分发,并注入到myframework.addons命名空间中.

Now, what I'm trying to arrange is so that these addons can be distributed separately from core framework and injected into myframework.addons namespace.

目前,我对此的最佳解决方案是.将会部署一个附件(很可能像这样在{python_version}/site-packages/中部署:

Currently my best solution to this is the following. An add-on would be deployed (most likely into {python_version}/site-packages/ like so:

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路径扩展代码:

The fooext/myframework/addons/__init__.py would have the pkgutil path extension code:

import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)

问题在于,要使其正常运行,PYTHONPATH需要包含fooext/,但是它唯一拥有的是父安装目录(最有可能是上述的site-packages).

The problem is that for this to work, the PYTHONPATH needs to have fooext/ in it, however the only thing it would have is the parent install directory (most likely, the above-mentioned site-packages).

解决方案是在myframework/addons/__init__.py中添加多余的代码,该代码将遍历sys.path并查找带有myframework子包的任何模块,在这种情况下,它将其添加到sys.path中,一切正常.

The solution to this is to have extra code in myframework/addons/__init__.py which would tranverse sys.path and look for any modules with a myframework sub-package, in which case it adds it to sys.path and everything works.

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

Another idea I had is to write the addon files directly to myframework/addons/ install location, but then it would make development and deployed namespace differ.

是否有更好的方法来解决上述问题,或者完全解决上述分配问题?

Is there a better way to accomplish this or perhaps a different approach to the above distribution problem altogether?

推荐答案

对于上述分配问题,是否有更好的方法来实现?或者完全不同?

Is there a better way to accomplish this or perhaps a different approach to the above distribution problem altogether?

可能. Python的模块/软件包设置通常很难像这样动态地进行篡改,但是它的对象/类系统是开放的,并且以明确定义的方式可扩展.当模块和软件包没有足够的功能来封装项目时,可以使用类.

Possibly. Python's module/package setup is generally tricky to tamper with dynamically like this, but its object/class system is open and extensible in a well-defined way. When modules and packages don't quite have the features you need to encapsulate your project nicely you can use classes instead.

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

For example you could have the extension functionality in a completely different package, but allow it to inject classes into your basic framework through a specific interface. eg. myframework/_​​_​init​_​​_.py containing a basic application wrapper:

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类实例的引用:

Then you could have extension functionality in a myexts/helloer.py, that keeps a reference to its 'owner' or 'outer' MyFramework class instance:

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().当然,您还可以定义用于附加组件与基本框架行为以及彼此交互的协议.如果需要这种复杂性,您还可以执行诸如内部类之类的事情,框架的子类可以重写以进行自定义,而不必猴子修补可能影响其他应用程序的类.

So now if you just "import myframework", you only get the basic functionality. But if you also "import myexts.helloer" you also get the ability to call MyFramework.helloer.hello(). Naturally you can also define protocols for addons to interact with the basic framework behaviour, and each other. You can also do things like inner classes a subclass of the framework can override to customise without having to monkey-patch classes that might affect other applications, if you need that level of complexity.

这样的封装行为可能很有用,但是要适应已经适合该模型的模块级代码,通常是令人讨厌的工作.

Encapsulating behaviour like this can be useful, but it's typically annoying work to adapt module-level code you've already got to fit this model.

这篇关于将单独的python包放入相同的名称空间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆