【发布时间】:2016-10-12 16:03:37
【问题描述】:
我正在尝试将我的 Python 代码放入用于使用 setup.py 和 PyPI 进行部署的标准目录结构中。对于名为 mylib 的 Python 库,它会是这样的:
mylibsrc/
README.rst
setup.py
bin/
some_script.py
mylib/
__init.py__
foo.py
通常还有一个test/ 子目录,但我还没有尝试编写单元测试。在official Python packaging documentation 中可以找到将脚本放在bin/ 子目录中的建议。
当然,脚本开头的代码如下所示:
#!/usr/bin/env python
from mylib.foo import something
something("bar")
这在最终部署脚本(例如到 devpi)然后使用 pip 安装时效果很好。但是,如果我直接从源目录运行脚本,就像在开发库/脚本的新更改时那样,我会收到以下错误:
ImportError: No module named 'mylib'
即使当前工作目录是根 mylibsrc/ 并且我通过键入 ./bin/some_script.py 运行脚本也是如此。这是因为 Python 开始在正在运行的脚本的目录(即来自 bin/)中搜索包,而不是当前工作目录。
在开发包时,有什么好的、永久的方法可以让脚本运行变得容易?
这是relevant other question(尤其是第一个答案的cmets)。
到目前为止,我发现的解决方案分为三类,但没有一个是理想的:
- 在运行脚本之前以某种方式手动修复 Python 的模块搜索路径。
- 您可以手动将
mylibsrc添加到我的PYTHONPATH环境变量中。这似乎是最官方的(Pythonic?)解决方案,但这意味着每次我签出一个项目时,我都必须记住手动更改我的环境,然后才能在其中运行任何代码。 - 将
.添加到我的PYTHONPATH环境变量的开头。据我了解,这可能存在一些安全问题。如果我是唯一一个使用我的代码的人,这实际上是我最喜欢的伎俩,但我不是,而且我不想要求其他人这样做。 - 在互联网上查看答案时,对于
test/目录中的文件,我看到建议它们都(间接)包含一行代码sys.path.insert(0, os.path.abspath('..'))(例如在 structuring your project 中)。呸!对于仅用于测试的文件,而不是那些将与软件包一起安装的文件,这似乎是一个可以忍受的 hack。 - 编辑:我后来找到了一个替代方案,结果证明属于这一类:通过使用 Python 的
-m脚本运行脚本,搜索路径从工作目录而不是bin/目录开始。有关详细信息,请参阅下面的答案。
- 您可以手动将
- 使用 setup.py(直接运行或使用 pip)在使用前将包安装到虚拟环境。
- 如果我只是在测试一个我甚至不确定在语法上是否正确的更改,这似乎有点过头了。我正在处理的一些项目甚至不打算作为包安装,但我想对所有内容使用相同的目录结构,这意味着编写一个 setup.py 以便我可以测试它们!
- 编辑:下面的答案中讨论了这两个有趣的变体:logc 的答案中的
setup.py develop命令和我的pip install -e。他们避免了每次小编辑都必须重新“安装”,但您仍然需要为您从未打算完全安装的软件包创建一个setup.py,并且与 PyCharm(它有一个菜单项可以运行develop命令,但没有简单的方法来运行它复制到虚拟环境的脚本)。
- 将脚本移动到项目的根目录(即在
mylibsrc/中而不是mylibsrc/bin/中)。- 糟糕!这是最后的手段
但不幸的是,这似乎是目前唯一可行的选择。
- 糟糕!这是最后的手段
【问题讨论】: