【问题标题】:Import local testing version of a Python namespace package导入 Python 命名空间包的本地测试版本
【发布时间】:2015-09-12 17:41:59
【问题描述】:

我想知道如何导入 Python 2.7 命名空间包的本地测试版本。在本例中,包Ska.engarchiveSka 根目录下的命名空间包。 (这种结构是由遗产强加给我的)。

这个例子表明,即使将sys.path 设置为从本地目录开始,导入的包的安装版本,而不是本地版本。

Python 2.7.9 |Continuum Analytics, Inc.| (default, Apr 14 2015, 12:54:25)
... 
In [1]: import sys
In [2]: sys.path.insert(0, '.')
In [3]: import Ska.engarchive.fetch_eng as fetch
In [4]: fetch.__file__
Out[4]: '/proj/sot/ska/arch/x86_64-linux_CentOS-5/lib/python2.7/site-packages/Ska.engarchive-0.36.2-py2.7.egg/Ska/engarchive/fetch_eng.pyc'

我认为问题与命名空间包在 Python 2 中实现的方式有关,无论如何命名空间路径总是位于列表的前面。但也许有一些解决方法?我花了一些时间研究 site 包文档,但也许我没有看到正确的东西。

以上示例使用 Anaconda Python 发行版。有趣的是,如果我使用来自 ActiveState 的非常旧的 Python 版本,则该示例具有导入本地包的预期结果:

Python 2.7.1 (r271:86832, Feb  7 2011, 11:30:54) 

In [1]: import sys
In [2]: sys.path.insert(0, '.')
In [3]: import Ska.engarchive.fetch_eng as fetch
In [4]: fetch.__file__
Out[4]: './Ska/engarchive/fetch_eng.pyc'

任何帮助将不胜感激!

【问题讨论】:

    标签: python python-2.7 python-import anaconda namespace-package


    【解决方案1】:

    我能够使用 setuptools 的 namespace packages 方法复制此行为(但不是标准的 pkgutil method)。 Setuptools 将导入已安装的包,而 pkgutil 将导入本地包。 Setuptools 似乎从您的预期(首先安装,本地第二)向后加载 __path__。例如,(参见底部示例了解 nstest 的定义)

    >>> import nstest
    >>> nstest.__path__
    ['/home/caleb/.local/lib/python2.7/site-packages/nstest.foo-0.0.0-py2.7.egg/nstest', 'nstest']
    

    解决这个问题的方法是将你的本地包添加到__path__ 前面的最右边的命名空间包中。例如,

    >>> import nstest
    >>> nstest.__path__.insert(0, 'nstest')
    >>> from nstest import foo
    >>> foo.__file__
    'nstest/foo/__init__.py'
    

    由于您在问题中说Ska.engarchive 是一个命名空间包,因此您希望在您的解释器中执行以下操作:

    >>> import Ska.engarchive
    >>> Ska.engarchive.__path__.insert(0, 'Ska/engarchive')
    >>> import Ska.engarchive.fetch_eng as fetch
    >>> fetch.__file__
    'Ska/engarchive/fetch_eng.pyc' # This should be outputted
    

    使用 setuptools 的 pkg_resources 进行命名空间测试

    目录结构:

    nstest.foo/
    ├─ setup.py
    └─ nstest/
       ├─ __init__.py
       └─ foo/
          └─ __init__.py
    

    nstest.foo/setup.py

    from setuptools import setup, find_packages
    setup(name='nstest.foo', packages=find_packages())
    

    nstest.foo/nstest/__init__.py

    __import__('pkg_resources').declare_namespace(__name__)
    

    nstest.foo/nstest/foo/__init__.py

    # empty
    

    安装:

    $ python2 setup.py build
    $ python2 setup.py install --user
    

    测试:

    $ python2
    >>> from nstest import foo
    >>> foo.__file__
    '/home/caleb/.local/lib/python2.7/site-packages/nstest.foo-0.0.0-py2.7.egg/nstest/foo/__init__.pyc'
    

    【讨论】:

    • 建议的修复工作完美。我没有意识到有不同的方式来实现命名空间包(使用pkgutil)所以这是一个双重有用的答案。
    猜你喜欢
    • 2017-12-20
    • 1970-01-01
    • 2013-06-05
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多