92

编辑:根据 Ulf Rompe 的评论,使用 "1" 而不是 "0" 很重要,否则会破坏sys.path

我做 python 已经有一段时间了(一年多了),我总是很困惑为什么人们推荐你使用sys.path.append()而不是sys.path.insert(). 让我演示一下。

假设我正在开发一个名为 PyWorkbooks 的模块(安装在我的计算机上),但我同时正在开发一个包含 PyWorkbooks 的不同模块(比如说 PyJob)。当我在 PyJob 上工作时,我发现我正在纠正的 PyWorkbooks 中的错误,所以我想导入一个开发版本。

有多种方法可以同时处理这两种方法(例如,我可以将我的 PyWorkbooks 项目放在 PyJob 中),但有时我仍然需要使用路径。但是,我不能简单地对sys.path.append()PyWorkbooks 所在的文件夹执行操作。为什么?因为python会先找到我安装的PyWorkbooks!

这就是为什么你必须做一个 sys.path.insert(1, path_to_dev_pyworkbooks)

总之:

sys.path.append(path_to_dev_pyworkbooks)
import PyWorkbooks # does NOT import dev pyworkbooks, imports installed one

或者:

sys.path.insert(1, path_to_dev_pyworkbooks) # based on comments you should use **1 not 0**
import PyWorkbooks # imports correct file

这在过去给我造成了一些挂断,如果我们(作为一个社区)开始推荐sys.path.insert(1, path),我真的很喜欢它,就像你手动插入一条路径我认为可以肯定地说那是你想要的路径使用!

还是我有什么问题?这是一个有时困扰我的问题,我希望它公开!

4

3 回答 3

50

如果您确实需要使用 sys.path.insert,请考虑保留 sys.path[0] 原样:

sys.path.insert(1, path_to_dev_pyworkbooks)

这可能很重要,因为第 3 方代码可能依赖于sys.path 文档一致性:

在程序启动时初始化时,此列表的第一项 path[0] 是包含用于调用 Python 解释器的脚本的目录。

于 2012-04-10T22:47:18.533 回答
48

如果您有多个版本的包/模块,则需要使用virtualenv(强调我的):

virtualenv是创建隔离 Python 环境的工具。

正在解决的基本问题是依赖关系和版本之一,以及间接权限。想象一下,您有一个应用程序需要 LibFoo 版本 1,但另一个应用程序需要版本 2。您如何同时使用这两个应用程序?如果您将所有内容都安装到/usr/lib/python2.7/site-packages(或任何您的平台的标准位置),很容易导致您无意中升级不应升级的应用程序。

或者更一般地说,如果你想安装一个应用程序并让它保持不变怎么办?如果应用程序正常工作,其库或这些库版本的任何更改都可能破坏应用程序。

另外,如果您无法将软件包安装到全局site-packages目录中怎么办?例如,在共享主机上。

在所有这些情况下,virtualenv都可以为您提供帮助。它创建了一个具有自己的安装目录的环境,它不与其他 virtualenv 环境共享库(并且可选地也不访问全局安装的库)。

这就是人们认为insert(0, 错误的原因——它是管理多个环境问题的不完整的权宜之计解决方案。

于 2012-04-10T19:23:47.757 回答
13

您混淆了附加和前置的概念。以下代码在前面:

sys.path.insert(1,'/thePathToYourFolder/')

它将新信息放在口译员将要经过的搜索序列的开头(准确地说是第二个)。sys.path.append()把事情放在搜索序列的最后。

建议您使用类似的东西,virtualenv而不是手动将包目录编码到PYTHONPATH每次。要设置将站点包和可能的 python 版本分开的各种生态系统,请阅读以下两个博客:

  1. python生态系统介绍

  2. 引导 python 虚拟环境

如果你决定走下环境隔离的道路,你肯定会通过研究 virtualenvwrapper 受益:http: //www.doughellmann.com/docs/virtualenvwrapper/

于 2012-06-24T18:01:20.733 回答