πŸ“œ ⬆️ ⬇️

"Pip -t" is a simple alternative to virtualenv

TL; DR


In order to simply install and isolate project dependencies, virtualenv is often too difficult a decision. We offer a simple alternative:
  1. add ./.pip to the PYTHONPATH environment variable,
  2. install packages locally with pip install -t .pip ,
  3. Run python from the project folder.


What version do you want today?


Installing dependencies is a required step for almost any Python application. Each application depends on different libraries, and to ensure its correct behavior, it is best to install exactly the right versions of the libraries.

A common practice is to include the requirements.txt file in the project. This file lists all the libraries on which the project depends, with version numbers. If the file is in place, installing the dependencies is simple:
 $ pip install -r requirements.txt 

So far so good. It will be bad if you have two or more projects with conflicting dependencies . Suppose project A is working with library X only version 0.1, and project B is 0.2. By default, pip installs libraries globally to the Python interpreter folder. This means that the $ pip install X==0.2 command will install the X version 0.2 library for all projects and will overwrite version 0.1 if it is already installed. Switching between A and B means a global reset of X each time, which is long and inconvenient.

Island under the sun


A popular solution to this common problem is virtual environments . The virtualenv framework creates isolated Python environments. The dependencies of each project are separated from each other. Anyway, for some users, virtualenv seems too complicated. Therefore, there are packages like virtualenvwrapper and autoenv that extend the functionality of virtualenv to make it easier to use. Other solutions: Anaconda environments and pyvenv from the standard Python library (3.3+).
')
All these are excellent tools, but it always seemed to us that they offer rather difficult and complicated solutions to a simple, in general, problem.

In the Javascript world, npm and Bower offer simple, reliable and powerful package management, which Python seems to lack. Their key to success is that they download the correct version of the correct library and put it in a special folder inside the project. Downloaded libraries refer only to a specific project. This automatically eliminates the problems mentioned above.

Pure magic


It turns out that there is a simple way to repeat the approach of npm and Bower in Python:

Then just run the code from the project folder. Forget about source env/bin/activate and deactivate !

Focus works because ./.pip is a relative path. As a result, when you run python from ~/dev/project_a , the ~/dev/project_a/.pip included in the list of library folders for this Python instance. Run python in ~/dev/project_b - it turns on ~/dev/project_b/.pip . Reception works on all popular platforms: Linux, Mac and Windows.

The name of the folder .pip , of course, can be any. Someone more like pip_components or libs . However, .pip quickly, and the dot at the beginning makes the folder hidden in Linux and Mac.

Step 1: Install PYTHONPATH




Step 2: Install packages with pip -t


Now that PYTHONPATH is installed, all that's left is to install the packages in the right place using pip. To do this, use the -t or --target :
 $ cd project_a project_a$ pip install requests==2.7.0 -t .pip project_a$ python >>> import requests >>> requests.__version__ '2.7.0' 

Now the same thing in another project with a different version:
 $ cd project_b project_b$ pip install requests==2.6.0 -t .pip project_b$ python >>> import requests >>> requests.__version__ '2.6.0' 

The requirements.txt file works the same way:
 $ pip install -r requirements.txt -t .pip 


Potential ambush


Different interpreters of Python


You can easily run the program with another Python interpreter:
 $ /path/to/python main.py 

However, there is a problem with switching between Python 2 and 3, if packages are used that compile the source code during installation via 2to3 . Such packages do not have a single code base; during installation, the code is generated according to the active version of Python.

In this case, create a folder of type .pip3 and add it to the beginning of PYTHONPATH when you run the code with Python 3.

easy_install


If you have packages installed globally via easy_install , you will encounter a problem: easy_install appends the path to such packages to the beginning of sys.path , so they have priority over packages from .pip .

The solution is to get rid of packages installed globally via easy_install.

To verify that nothing prevents you from using .pip, run import sys;sys.path in Python. If ./.pip are other paths in front of ./.pip , you may have to clean the system of global easy_install packages first.

Source: https://habr.com/ru/post/261263/


All Articles