Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prepend a path to sys.path in Python?

Problem description:

Using pip, I upgraded to the latest version of requests (version 2.7.0, with pip show requests giving the location /usr/local/lib/python2.7/dist-packages). When I import requests and print requests.__version__ in the interactive command line, though, I am seeing version 2.2.1. It turns out that Python is using the pre-installed Ubuntu version of requests (requests.__file__ is /usr/lib/python2.7/dist-packages/requests/__init__.pyc -- not /user/local/lib/...).

From my investigation, this fact is caused by Ubuntu's changes to the Python search path (I run Ubuntu 14.04) by prepending the path to Ubuntu's Python package (for my machine, this happens in usr/local/lib/python2.7/dist-packages/easy-install.pth). In my case, this causes the apt-get version of requests, which is pre-packaged with Ubuntu, to be used, rather than the pip version I want to use.

What I'm looking for:

I want to globally prepend pip's installation directory path to Python's search path (sys.path), before the path to Ubuntu's Python installation directory. Since requests (and many other packages) are used in many Python scripts of mine, I don't want to manually change the search path for every single file on my machine.

Unsatisfactory Solution 1: Using virtualenv

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.

Unsatisfactory Solution 2: Changing easy-install.pth

Since easy-install.pth is overwritten every time easy-install is used, my changes to easy-install.pth would be removed if a new package is installed. This problem makes it difficult to maintain the packages on my machine.

Unsatisfactory (but best one I have so far) Solution 3: Adding a separate .pth file

In the same directory as easy-install.pth I added a zzz.pth with contents:

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) 

This file is read by site.py when Python is starting. Since its file name comes after easy-install.pth alphanumerically, it is consumed by site.py afterwards. Taken together, the first and last lines of the file prepend the path to sys.path (these lines were taken from easy-install.pth).

I don't like how this solution depends on the alphanumeric ordering of the file name to correctly place the new path.

PYTHONPATHs come after Ubuntu's paths

Another answer on Stack Overflow didn't work for me. My PYTHONPATH paths come after the paths in easy-install.pth, which uses the same code I mention in "Unsatisfactory solution 3" to prepend its paths.

Thank you in advance!

like image 227
max Avatar asked Jul 14 '15 18:07

max


People also ask

How do you append a path in Python?

APPENDING PATH- append() is a built-in function of sys module that can be used with path variable to add a specific path for interpreter to search. The following example shows how this can be done.

What is SYS path in Python?

Sys. path is a list of directories where the Python interpreter searches for modules.

What is the difference between SYS path insert And SYS path append?

1) insert and append methods are not specific to sys. path and as in other languages they add an item into a list or array and : * append(item) add item to the end of the list, * insert(n, item) inserts the item at the nth position in the list ( 0 at the beginning, 1 after the first element, etc ...).

How does Python set SYS path?

By default, sys. path is constructed as a concatenation of (1) the current working directory, (2) content of PYTHONPATH environment variable, and (3) a set of default paths supplied by the installed Python interpreter. The error can occur either because the module is indeed missing on your system, or because the sys.


2 Answers

This is not recommended, as it hard-codes a path and makes it difficult to run the script elsewhere, but you can do

>>> import sys >>> sys.path.insert(0,'/home/anand/') >>> 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'] >>> 

After this your imports will look into the prepended path before looking anywhere else.

like image 131
Software Mechanic Avatar answered Sep 21 '22 03:09

Software Mechanic


You shouldn't need to mess with pip's path, python actually handles it's pathing automatically in my experience. It appears you have two pythons installed. If you type:

which pip which python 

what paths do you see? If they're not in the same /bin folder, then that's your problem. I'm guessing that the python you're running (probably the original system one), doesn't have it's own pip installed. You probably just need make sure the path for the python you want to run should come before /usr/bin in your .bashrc or .zshrc

If this is correct, then you should see that:

which easy_install 

shares the same path as the python installation you're using, maybe under /usr/local/bin. Then just run:

easy_install pip 

And start installing the right packages for the python that you're using.

like image 34
fivetentaylor Avatar answered Sep 23 '22 03:09

fivetentaylor