如何在Python中预先添加sys.path的路径?

时间:2015-07-14 18:03:05

标签: python ubuntu pip easy-install pythonpath

问题描述:

使用pip,我升级到最新版本的requests(版本2.7.0,pip show requests,其位置为/usr/local/lib/python2.7/dist-packages)。但是,当我在交互式命令行中import requests并打印requests.__version__时,我看到版本2.2.1。事实证明,Python正在使用预先安装的Ubuntu版本的请求(requests.__file__/usr/lib/python2.7/dist-packages/requests/__init__.pyc - 而不是/user/local/lib/...)。

从我的调查来看,这个事实是由Ubuntu对Python搜索路径的改变(我运行Ubuntu 14.04)引起的,它是通过在Ubuntu的Python包之前添加路径(对于我的机器,这发生在usr/local/lib/python2.7/dist-packages/easy-install.pth)。就我而言,这会导致使用预先打包在Ubuntu中的apt-get版本的请求,而不是我想要使用的pip版本。

我在寻找什么:

我希望在到Ubuntu的Python安装目录的路径之前,将pip的安装目录路径全局预先添加到Python的搜索路径(sys.path)。由于在我的许多Python脚本中使用了请求(以及许多其他包),我不想手动更改计算机上每个文件的搜索路径。

不满意的解决方案1:使用virtualenv

使用virtualenv会对我的计算机造成不必要的更改,因为我必须重新安装全局存在的每个包。我只想从Ubuntu的软件包升级到pip的软件包。

不满意的解决方案2:更改easy-install.pth

由于每次使用easy-install.pth时都会覆盖easy-install,因此如果安装了新软件包,我将删除对easy-install.pth的更改。这个问题使我很难在我的机器上维护包。

不满意(但我到目前为止最好)解决方案3:添加单独的.pth文件

在与easy-install.pth相同的目录中,我添加了zzz.pth内容:

import sys; sys.__plen = len(sys.path)
/usr/lib/python2.7/dist-packages/test_dir
import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)

当Python启动时,site.py会读取此文件。由于其文件名以字母数字easy-install.pth之后出现,因此site.py之后将其消耗。总之,文件的第一行和最后一行在sys.path的路径前面(这些行来自easy-install.pth)。

我不喜欢这个解决方案如何依赖文件名的字母数字排序来正确放置新路径。

PYTHONPATHs来自Ubuntu的路径

Stack Overflow上的

Another answer对我不起作用。我的PYTHONPATH路径位于easy-install.pth中的路径之后,它使用我在“不满意的解决方案3”中提到的相同代码来添加其路径。

提前感谢您!

8 个答案:

答案 0 :(得分:8)

这不推荐*,但是来自你的python脚本 你可以做到

>>> import sys
>>> b = sys.path
>>> sys.path = ['/home/anand/'] + b
>>> print(sys.path)
['/home/anand/', '', '/usr/local/lib/python2.7/dist-packages/_pdbpp_path_hack', '/usr/local/lib/python2.7/dist-packages/goose-0.0.1-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/jieba-0.33-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/cssselect-0.9.1-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/nanoservice-0.1.5-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/nanomsg-1.0a2-py2.7-linux-x86_64.egg', '/usr/local/lib/python2.7/dist-packages/msgpack_python-0.4.2-py2.7-linux-x86_64.egg', '/usr/local/lib/python2.7/dist-packages/DecisionTree-2.2.5-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/nudepy-0.2-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/wsgilog-0.3-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/distribute-0.7.3-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/PIL-1.1.7-py2.7-linux-x86_64.egg', '/usr/local/lib/python2.7/dist-packages/MySQL_python-1.2.5-py2.7-linux-x86_64.egg', '/usr/local/lib/python2.7/dist-packages/munkres-1.0.7-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/parsedatetime-1.4-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/argparse-1.3.0-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/tusker-0.1-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/SQLAlchemy-1.0.3-py2.7-linux-x86_64.egg', '/usr/local/lib/python2.7/dist-packages/numpy-1.9.2-py2.7-linux-x86_64.egg', '/usr/local/lib/python2.7/dist-packages/turkic-0.2.5-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/scikits.bootstrap-0.3.2-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/pyvision-0.1-py2.7-linux-x86_64.egg', '/home/anand/playspace/languages/python_pkgs/ets', '/usr/local/lib/python2.7/dist-packages/Scrapy-1.1.0dev1-py2.7.egg', '/usr/lib/python2.7/dist-packages', '/home/anand/playspace', '/home/anand/workspace/pyvision/src', '/home/anand/playspace/yapf', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/local/lib/python2.7/dist-packages/Orange/orng', '/usr/local/lib/python2.7/dist-packages/PIL', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gst-0.10', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/wx-3.0-gtk2']
>>>

在此之后,您的导入将在查找其他任何位置之前查看前置路径。

  • - 用于路径的硬编码以及脚本无法在其他任何地方运行。

答案 1 :(得分:7)

你不应该捣乱pip的路径,python实际上在我的经验中自动处理它的路径。看来你安装了两个蟒蛇。如果输入:

which pip
which python
你看到了什么样的路径?如果它们不在同一个/ bin文件夹中,那那就是你的问题。我猜你正在运行的python(可能是最初的系统),没有安装自己的pip。您可能只需要确保要运行的python的路径应该位于.bashrc或.zshrc中的/ usr / bin之前

如果这是正确的,那么你应该看到:

which easy_install

与你正在使用的python安装共享相同的路径,可能在/ usr / local / bin下。然后运行:

easy_install pip

然后开始为你正在使用的python安装正确的软件包。

答案 2 :(得分:3)

  

使用virtualenv会对我的机器造成不必要的更改,因为我必须重新安装全局存在的每个包。我只想从Ubuntu的软件包升级到pip的软件包。

不,您可以使用--system-site-packages

修改

- (NSMutableArray*)sortArray:(NSMutableArray*)dataArray filterKeyName:(NSString*)KeyName ascending:(BOOL)isAscending{

        NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:KeyName ascending:isAscending];
        [dataArray sortUsingDescriptors:[NSArray arrayWithObject:sorter]];

        return dataArray; // Sorted data array..
    }

如您所见,此virtualenv的路径包括系统路径。 为了检查它是否正常工作,我在制作virtualenv之后在系统范围内安装了

# make your new virtualenv
user@darkstar:~$ mkvirtualenv --system-site-packages max
(max)user@darkstar:~$ python
>>> pprint(sys.path)
['',
 '/home/user/.virtualenvs/max/lib64/python27.zip',
 '/home/user/.virtualenvs/max/lib64/python2.7',
 '/home/user/.virtualenvs/max/lib64/python2.7/plat-linux2',
 '/home/user/.virtualenvs/max/lib64/python2.7/lib-tk',
 '/home/user/.virtualenvs/max/lib64/python2.7/lib-old',
 '/home/user/.virtualenvs/max/lib64/python2.7/lib-dynload',
 '/usr/lib64/python2.7',
 '/usr/lib/python2.7',
 '/usr/lib64/python2.7/lib-tk',
 '/home/user/.virtualenvs/max/lib/python2.7/site-packages',
 '/usr/lib64/python2.7/site-packages/google_api_python_client-1.2-py2.7.egg',
 '/usr/lib64/python2.7/site-packages',
 '/usr/lib64/python2.7/site-packages/PIL',
 '/usr/lib64/python2.7/site-packages/gtk-2.0',
 '/usr/lib64/python2.7/site-packages/IPython/extensions']

显然,virtualenv中安装的内容优先于系统范围的库。

我相信能满足你的需求。

答案 3 :(得分:3)

回答直接问题

您可以在sitecustomize目录中创建名为site-packages的目录。我们将其转换为sitecustomize模块,如here所述(Python 2 here)。具体做法是:

  

尝试导入名为sitecustomize的模块,该模块可以执行任意特定于站点的自定义。它通常由site-packages目录中的系统管理员创建。

sitecustomize目录中创建一个名为__init__.py的文件,并添加您想要在那里执行的操作。一个非常简单的例子是:

import sys
sys.path = ['/your/path/to/pip/install'] + sys.path

在您的情况下,我认为your/path...将是/usr/local/lib/python2.7/dist-packages。你可能想要做一些更复杂的事情,但这粗略地预先设置sys.path并在每次启动python时运行(例如在命令行中启动解释器,或从文件运行python脚本)。

买者

我不是这样做的大力倡导者 - 这是做你想做的事情的一种直率方式。但是你明确地说使用virtualenv对你来说是不受欢迎的,你想要“全局”地做出改变,我想这会做你想要的。

关于潜在问题的想法

我认为@ fivetentaylor的answer在这里是正确的轨道 - 看来你正在使用pip从一个安装python可执行文件到另一个安装。通过弄乱路径掩盖这一点可能会很快变得非常混乱。我肯定会确保每次安装pip都有一个单独的python,您就可以使用它。这应该保持单独安装的目录结构分开。否则,您强制一次安装使用来自不同安装目录的软件包。在技​​术上没有问题,但在后勤方面令人困惑。

答案 4 :(得分:2)

嗯,其他人提出的替代方案是非常可以接受的,甚至可能更好。但是,如果您打算使用sys.path()方式,那么只需将其视为列表并使用insert方法。

import sys
sys.path.insert(0, "path_to_pip") 
from subprocess import call
call("sudo pip install requests") 

答案 5 :(得分:2)

我会按照sitecustomize文档中的说明使用site.py执行此操作。在配置初始sys.path后导入此文件,您可以根据需要以任意方式使用它来更改sys.path

我已将它用作系统管理员以包含自定义发布位置,并且它可以很好地完成工作。

https://docs.python.org/2/library/site.html

答案 6 :(得分:1)

虽然bufh's答案现在可以解决您的问题,但您可能会发现其他一些您不想使用Ubuntu提供的版本的软件包。所以,这就是为什么你想使用virtualenvs来管理包的版本(而不是试图覆盖系统版本)。

正如您所注意到的,sys.path的顺序设置了找到python包的顺序。这意味着更改sys.path会影响python脚本查找其导入的方式,包括您编写的脚本和 Ubuntu提供的脚本。鉴于在Ubuntu程序中使用python脚本,它可能会打破"破坏"通过改变Ubuntu程序使用哪个版本的python包来解决Ubuntu问题(这就是dist-packages存在的原因)。

为了避免这种情况,创建了virtualenv,这有效地允许使用不同的包集。现在有很多实用程序可以更轻松地使用和管理virtualenvs。可能对您最感兴趣的是pipsi,它为每个脚本创建了一个virtualenv,并且无需激活它。

答案 7 :(得分:1)

从事情的声音来看,Ubuntu正在使用包含文件here的包路径配置文件来设置它安装的任何软件包。

查看site.py我看到路径解析的特定顺序在解析站点包目录时调用配置文件。

我认为这给了我三个选项:

  1. 根据@ bufh的回答使用virtualenv --system-site-packages。
  2. 使用pip user installs在标准网站套餐之前的路径中设置所需的软件包。
  3. 使用sitecustomize重新编写sys.path(例如,将本地目录放在第一位)。