为什么要使用sys.path.append(path)而不是sys.path.insert(1, path)?

94

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

我已经写了一段时间的Python(超过一年),我总是困惑于为什么人们推荐使用sys.path.append()而不是sys.path.insert()。 让我来举个例子。

假设我正在开发一个名为PyWorkbooks的模块(已安装在我的计算机上),但同时我也在开发另一个模块(比如说PyJob),它包含PyWorkbooks。 当我在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
我已经执行了sys.path.insert(1, dev_folder),但仍然找不到开发模块,只能使用安装的模块。我该怎么解决这个问题? - endolith
3个回答

54

如果你真的需要使用sys.path.insert,请考虑保留sys.path[0]不变:

sys.path.insert(1, path_to_dev_pyworkbooks)

这可能很重要,因为第三方代码可能依赖于 sys.path文档 符合性:

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


51
如果您有多个版本的软件包/模块,您需要使用virtualenv(重点是我的):

virtualenv 是一个创建独立 Python 环境的工具。

它解决的基本问题是依赖关系和版本问题,间接地也涉及到权限。 想象一下,你有一个需要 LibFoo 版本 1 的应用程序,但另一个应用程序需要版本 2。怎么同时使用这两个应用程序呢? 如果你把所有东西都安装在 /usr/lib/python2.7/site-packages(或者你所在平台的标准位置)中,很容易陷入这样一种情况:你意外升级了不应该升级的应用程序。

或者更普遍的情况是,如果你想安装一个应用程序并且让它保持不变呢?如果一个应用程序可以正常工作,那么其库的任何更改或这些库的版本更改都可能会破坏该应用程序。

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

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

这就是为什么人们认为insert(0, 是错误的——它只是管理多个环境问题的不完整临时解决方案。

谢谢,我有点模糊地知道这样的东西存在,但直到现在我才真正去看它。所以我需要做的就是从虚拟环境中的解释器运行所有内容……那也可以。谢谢! - Garrett Berg
2
这只是一个建议,但并没有直接回答问题(例如,我有很强的理由不使用virtualenv,实际上正在寻找与OP相关的答案)。 - WestCoastProjects
@javadba 对于你的情况可能是正确的,但大多数询问这个问题的人应该使用 venv - agf

13
你混淆了添加和前置的概念。以下代码是前置的:

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

它将新信息放置在搜索序列的开头(准确地说是第二个),这是您的解释器将要经过的。 sys.path.append() 将事物放置在搜索序列的末尾。建议使用类似于virtualenv这样的东西,而不是每次手动编码包目录到PYTHONPATH中。为了设置分离您的网站包和可能的 Python 版本的各种生态系统,请阅读这两篇博客:python ecosystems introductionbootstrapping python virtual environments。如果您决定走向环境隔离之路,那么您一定会受益于研究 virtualenvwrapper:http://www.doughellmann.com/docs/virtualenvwrapper/

1
链接“Python生态系统介绍”和“引导Python虚拟环境”的页面已经下线,请考虑重新启用它们。 - Pradeep Singh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接