将第三方软件包目录添加到Python路径开头的最简洁方法是什么?

时间:2014-09-07 11:46:42

标签: python google-app-engine python-2.7 python-import pythonpath

我的上下文是appengine_config.py,但这确实是一个普通的Python问题。

鉴于我们克隆了其中包含空目录lib的应用程序的回购,并且我们使用命令lib使用包填充pip install -r requirements.txt --target lib,然后:

dirname ='lib'
dirpath = os.path.join(os.path.dirname(__file__), dirname)

出于导入目的,我们可以通过以下方式将这样的文件系统路径添加到Python路径的开头(我们使用索引1,因为第一个位置应保留'。',当前目录):

sys.path.insert(1, dirpath)

但是,如果该目录中的任何软件包都是命名空间软件包,那么这将无效。

要支持命名空间包,我们可以使用:

site.addsitedir(dirpath)

但是,这会将新目录附加到路径的 end ,我们不需要这样做,以防我们需要使用更新版本覆盖平台提供的包(例如WebOb)。

我到目前为止的解决方案是这段代码,我真的想简化:

sys.path, remainder = sys.path[:1], sys.path[1:]
site.addsitedir(dirpath)
sys.path.extend(remainder)

是否有更清洁或更多的Pythonic方法来实现这一目标?

2 个答案:

答案 0 :(得分:1)

对于这个答案,我假设您知道如何使用setuptoolssetup.py

假设您希望使用标准setuptools工作流进行开发,我建议您在appengine_config.py中使用此代码:

import os
import sys

if os.environ.get('CURRENT_VERSION_ID') == 'testbed-version':
    # If we are unittesting, fake the non-existence of appengine_config.
    # The error message of the import error is handled by gae and must
    # exactly match the proper string.
    raise ImportError('No module named appengine_config')


# Imports are done relative because Google app engine prohibits
# absolute imports.
lib_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'libs')
# Add every library to sys.path.
if os.path.isdir(lib_dir):
    for lib in os.listdir(lib_dir):
        if lib.endswith('.egg'):
            lib = os.path.join(lib_dir, lib)
            # Insert to override default libraries such as webob 1.1.1.
            sys.path.insert(0, lib)

setup.cfg中的这段代码:

[develop]
install-dir = libs
always-copy = true

如果键入python setup.py develop,则库将作为鸡蛋下载到libs目录中。 appengine_config将它们插入您的路径。

我们在工作中使用它来包含webob==1.3.1和使用我们公司名称空间命名的内部包。

答案 1 :(得分:0)

您可能想要查看Stack Overflow线程中的答案“How do I manage third-party Python libraries with Google App Engine? (virtualenv? pip?)”,但是对于您使用命名空间包的特定困境,您正在遇到a long-standing issue I filed against site.addsitedir's behavior of appending to sys.path instead of inserting after the first element。请随意添加该讨论,并附上此用例的链接。

我确实想解决你说的其他我认为有误导性的事情:

  

我的上下文是appengine_config.py,但这实际上是一般的Python   问题

问题实际上源于Google App Engine的限制以及无法安装第三方软件包,因此寻求解决方法。而不是手动调整sys.path并使用site.addsitedir。在一般 Python开发中,如果你的代码使用了这些,你就是在做错了。

Python Packaging Authority (PyPA) describes the best practices to put third party libraries on your path,我在下面概述:

  1. 创建virtualenv
  2. setup.py和/或要求文件中标出您的依赖关系(请参阅PyPA's "Concepts and Analyses"
  3. 使用pip
  4. 将依赖项安装到virtualenv中
  5. 使用pip和-e/--editable标志将项目本身安装到virtualenv中。
  6. 不幸的是,Google App Engine与virtualenv和pip不兼容。 GAE选择阻止此工具集尝试沙箱环境。因此,必须使用hacks来解决GAE的限制,以使用其他或更新的第三方库。

    如果您不喜欢此限制并希望使用标准Python工具来管理第三方软件包依赖项,那么other Platform as a Service providers会急切等待您的业务。