是否可以在现有包的名称空间/路径中添加一些不是命名空间包的东西?
假设有一个名为package
的外部包。
我在我的project.py
中使用它:
from package.module import Class
是否可以将名为extension
的程序包创建为package
的名称空间,以便可以从package.extension
导入?
from package.module import Class
from package.extension.module import ExtensionClass
是否可以使用pip
/ setuptools
安装这两个软件包,而无需在我project.py
package
中添加猴子修补程序,我要从package.extension
和{{} { 1}}?
我已经能够通过两种方式实现我的需求:修改原始package
和project.py
中的猴子修补
结构:
./test.py
./demo/test.py
./demo/__init__.py
./extension/demo/__init__.py
./extension/demo/extension/test.py
./extension/demo/extension/__init__.py
./extension/__init__.py
./test.py
的内容:
import demo.test
demo.test.hello()
import demo.extension.test
demo.extension.test.hello()
我修改了demo/__init__.py
,因此它包含:
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
执行示例:
$ export PYTHONPATH=extension
$ python test.py
Hello! I'm demo.
Hello! I'm extension.
我修改了./test.py
所以它包含了猴子补丁:
import pkgutil
import demo
demo.__path__ = pkgutil.extend_path(demo.__path__, demo.__name__)
import demo.test
demo.test.hello()
import demo.extension.test
demo.extension.test.hello()
执行示例:
$ export PYTHONPATH=extension
$ python test.py
Hello! I'm demo.
Hello! I'm extension.
其中一个解决方案要求原始软件包的所有者允许扩展,另一个解决方案需要猴子修补。是否有可能通过setup.py/pip安装的软件包不需要修改原始软件包或猴子修补?
答案 0 :(得分:1)
这可能不太有用,但您可以查看Flask和部分its extensions来源。 Flask扩展的工作方式与您描述的完全相同,例如:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
答案 1 :(得分:1)
我认为命名空间包是setuptools的一个功能,the docs只说明两个条件:
namespace_packages
和中setup()
__import__('pkg_resources').declare_namespace(__name__)
在你的
__init__.py
个文件。有了这个,我在Windows 7上使用Python 3.3测试了以下配置:
│ setup.py
│
└───cherrypy
│ __init__.py
│
└───extend
│ test.py
│
└───__init__.py
我的setup.py:
from setuptools import setup, find_packages
setup(
name = "HelloWorld",
version = "0.1",
packages = find_packages(),
namespace_packages = ['cherrypy']
)
然后,在python setup.py develop
之后,cherrypy.extend像模块一样工作,我可以从中加载类:
Python 3.3.5 (v3.3.5:62cf4e77f785, Mar 9 2014, 10:37:12) [MSC v.1600 32 bit (In
tel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import cherrypy
>>> cherrypy
<module 'cherrypy' from 'C:\\Python33\\lib\\site-packages\\cherrypy\\__init__.py
'>
>>> from cherrypy.extend import Cls
>>> from cherrypy.extend import test
>>> test
<module 'cherrypy.extend.test' from 'c:\\users\\me\\desktop\\test\\cherrypy\
\extend\\test.py'>
>>> o = Cls()
>>> o
<cherrypy.extend.Cls object at 0x01AA0AB0>
>>>
我还没有用pip测试可安装性,但似乎没有任何东西可以让它变得不可能。如果这不适合您,和/或您处于不同的环境中,请告诉我们。
编辑:我注意到我从我的包的源文件夹运行Python,它从./加载。这仍然按预期工作,我将上面的示例换成了我正在使用其他工作目录的示例。