构建 python 个项目而不用修改路径

Structuring python projects without path hacks

我有一个在多个项目中使用的共享 python 库,因此结构如下所示:

Project1
    main.py <--- (One of the projects that uses the library)
...
sharedlib
    __init__.py
    ps_lib.py
    another.py

现在在每个项目的 main.py 中,我使用以下 hack 使其工作:

import os
import sys
sys.path.insert(0, os.path.abspath('..'))

import sharedlib.ps_lib
...

有没有办法不使用这个 hack 来做到这一点?或者有没有更好的方式来组织项目结构?

我们的方法是对 python 脚本使用 bash 入口脚本。我们的目录结构类似于以下内容:

/opt/Whosebug/
                 -> bin
                 -> conf
                 -> lib
                 -> log

然后我们的 lib 文件夹包含我们所有的子项目

/opt/Whosebug/lib/
                    -> python_algorithms
                    -> python_data_structures
                    -> python_shared_libraries

然后当我们要执行python脚本时,我们将通过bin目录bash中的bash脚本执行它

/opt/Whosebug/bin/
                    -> quick_sort.sh
                    -> merge_sort.sh

如果我们 cat 我们的入口脚本之一

cat merge_sort.sh

#!/bin/bash
export Whosebug_HOME=/opt/Whosebug
export Whosebug_BIN=${Whosebug_HOME}/bin
export Whosebug_LIB=${Whosebug_HOME}/lib
export Whosebug_LOG=${Whosebug_HOME}/log
export Whosebug_CONF=${Whosebug_HOME}/conf

# Do any pre-script server work here

export PYTHONPATH=${PYTHONPATH}:${Whosebug_LIB}

/usr/bin/python "${Whosebug_LIB}/python_algorithms/merge_sort.py" $* 2>&1

我认为最好的方法是制作 sharedlib 一个真正的包。这意味着稍微改变一下结构:

sharedlib/
    sharedlib/
        __init__.py
        ps_lib.py
        another.py
    setup.py

并在 setup.py 中使用类似的东西(部分摘自 Python-packaging "Minimal Structure"):

from setuptools import setup

setup(name='sharedlib',
      version='0.1',
      description='...',
      license='...',
      packages=['sharedlib'],   # you might need to change this if you have subfolders.
      zip_safe=False)

然后在 sharedlib 包的根文件夹中使用 python setup.py develop or pip install -e . 安装它。

这样(使用 develop-e 选项)对 sharedlib/sharedlib/* 文件内容的更改将在不重新安装 sharedlib 包的情况下可见 - 虽然如果您在交互式解释器中工作,您可能需要重新启动解释器。那是因为解释器缓存了已经导入的包。

来自 setuptools 文档:

Setuptools allows you to deploy your projects for use in a common directory or staging area, but without copying any files. Thus, you can edit each project’s code in its checkout directory, and only need to run build commands when you change a project’s C extensions or similarly compiled files. [...]

To do this, use the setup.py develop command.

(强调我的)

最重要的是您现在可以在任何地方 import sharedlib - 不再需要在 PATHPYTHONPATH 中插入 sharedlib 包,因为 Python(或至少安装它的 Python)现在将 sharedlib 视为任何其他已安装的软件包。