当前位置: 首页>>技术问答>>正文


在Python中,如何在sys.path之前添加路径?

, , , ,

问题描述

问题描述:

使用pip,我升级到最新版本的requests(版本2.7.0,带有pip show requests,给出位置/usr/local/lib/python2.7/dist-packages)。但是,当我在交互式命令行中使用import requests并打印requests.__version__时,我看到的是版本2.2.1。事实证明,Python正在使用pre-installed 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中)。在我的情况下,这会导致使用apt-get版本的请求,即使用Ubuntu的pre-packaged,而不是我想要使用的pip版本。

我在找什么:

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

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

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

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

由于每次使用easy-install时都会覆盖easy-install.pth,因此如果安装了新软件包,我将删除对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中的路径之后,它使用我在“Unsatisfactory solution 3”中提到的相同代码来添加其路径。

先感谢您!

最佳解决方法

这不推荐*,但是你可以从你的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']
>>>

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

  • – 对于路径的硬编码和脚本无法在其他任何地方运行。

次佳解决方法

你不应该捣乱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安装正确的软件包。

第三种解决方法

Using virtualenv would cause an unnecessary amount of change to my machine, since I would have to reinstall every package that exists globally. I only want to upgrade from Ubuntu’s packages to pip’s packages.

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

编辑

# 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的路径包括系统路径。为了检查它是否正常工作,我在制作virtualenv之后安装了一个包system-wide。

root@darkstar:~: pip install igraph
Collecting igraph
  Downloading igraph-0.1.8-py2.py3-none-any.whl (119kB)
    100% |████████████████████████████████| 122kB 1.7MB/s
Collecting ipython (from igraph)
  Downloading ipython-3.2.1-py2-none-any.whl (3.4MB)
    100% |████████████████████████████████| 3.4MB 203kB/s 
Installing collected packages: ipython, igraph
Successfully installed igraph-0.1.8 ipython-3.2.1
root@darkstar:~: python -c 'print __import__("igraph")'
<module 'igraph' from '/usr/lib64/python2.7/site-packages/igraph/__init__.pyc'>

(max)user@darkstar:max$ python -c 'print __import__("igraph")'
<module 'igraph' from '/usr/lib64/python2.7/site-packages/igraph/__init__.pyc'>

显然,virtualenv中安装的内容优先于system-wide库。

我相信能满足你的需求。

第四种方法

回答直接问题

您可以在site-packages目录中创建名为sitecustomize的目录。我们将把它变成一个sitecustomize模块,如描述here(Python 2 here)。特别:

an attempt is made to import a module named sitecustomize, which can perform arbitrary site-specific customizations. It is typically created by a system administrator in your site-packages directory.

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脚本)。

Caveat

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

对潜在问题的思考

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

第五种方法

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

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

第六种方法

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

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

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

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/6364.html,未经允许,请勿转载。