[PYTHON] What Rubyist should know when using pyenv

Introduction

I think that the number of Rubyists who are starting to touch Python has increased due to the machine learning boom. At that time, environment construction is likely to be a problem. In Ruby, rbenv is the de facto standard, but for some reason Python has a lot of negative opinions about pyenv.

I'm using pyenv and find it useful. I also rarely use Ruby, but I also investigated the differences between the tool stacks of Ruby and Python. (Reference: Comparison of gem, bundler and pip, venv)

From that point of view, I would like to summarize the differences between Ruby and Python environments that Ruby users should know when deciding how to use pyenv for themselves.

tl;dr

Even if I explain it carefully, there are people who immediately read negatively that "I have to read such a long article to use Python", so I will summarize it in 4 lines.

  1. For applications that do not use Bundler in Ruby, pyenv and rbenv are almost the same.
  2. When using Bundler, Python uses venv, but venv also fixes the Python version, so pyenv local is not needed.
  3. It is convenient to use pyenv-virtualenv, but shims gets dirty because it is like managing Bundler with rbenv.
  4. On the contrary, it is also possible to use pyenv only for build without using shims and without making the shell heavy.

Difference between Bundler and venv

The division of roles of package management tools is slightly different between Ruby and Python. Python's pip has features such as dependency resolution and version locking, so in that respect it includes some of the role of Bundler as well as gem.

On the other hand, the function to manage packages independently for each project (Bundler's bundle install --path) is venv. I use a tool called. [^ 1](Reference: [bundler --path and venv](http://qiita.com/methane/items/570728ad3e79c74f4e9e#bundler-%E3%81%AE --- path-% E3% 81% A8 -venv)))

The big difference between venv and bundle install --path is that venv behaves like Python set up independently, rather than just storing packages. This is called a "virtual environment". The virtual environment is more compact than the real installed Python environment because the standard library is the same as the original Python. See the following example.

$ python3 -m venv .venv  # .Create a virtual environment in a directory named venv.

$ ls -F .venv/
bin/                include/            lib/                pip-selfcheck.json  pyvenv.cfg

$ .venv/bin/pip install tornado
Collecting tornado
Installing collected packages: tornado
Successfully installed tornado-4.5.1

$ .venv/bin/python
Python 3.6.1 (default, May 18 2017, 16:23:51)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tornado

As you can see, in a virtual environment you can call pip install with no options like you would normally install a library in Python, and virtual without doing something like bundle exec ruby. Python in the environment can import the installed libraries.

Now, the big difference from bundle exec in Ruby is that the Python version of the virtual environment is determined when you create the virtual environment, so it is enough to specify which version of Python to use only once when creating the virtual environment. .. This means that you don't have to configure pyenv local to use the same version of Python every time. [^ 2]

[^ 2]: I think this difference is the reason why pyenv has so many negative opinions about "is there a merit to bring magic into the shell and slow it down?"

There are several ways to temporarily specify the Python version only when creating a virtual environment.

$ pyenv shell 3.6.1
$ python -m venv venv
$ pyenv shell --unset
(Or)
$ `pyenv root`/versions/3.6.1/bin/python -m venv venv

[^ 1]: I have the pip install --target or pip install --prefix option, but there is no command equivalent to bundle exec and I own PYTHONPATH Must be set in. I don't recommend it because it's not a very common practice.

About activate of virtual environment

Virtual environments created with venv can be "activated". "activate" will add the bin directory of the virtual environment to the beginning of the environment variable PATH, so you can run the command just like pip instead of venv / bin / pip.

The environment variable VIRTUAL_ENV is also set. Vim's Python completion plugin etc. will look at this environment variable and perform method completion for the imported library.

$ . venv/bin/activate  #Activate the virtual environment

$ echo $VIRTUAL_ENV
/Users/inada-n/tmp/venv

$ which python
/Users/inada-n/tmp/venv/bin/python

$ which pip
/Users/inada-n/tmp/venv/bin/pip

$ deactivate  #Command to activate activate

$ which python
/Users/inada-n/pyenv/shims/python

About pyenv-virtualenv

pyenv-virtualenv is a tool for managing virtual environments using the functions of pyenv. It has the following advantages.

  1. Supports Python 2 that does not have venv in the standard library with a third-party tool called virtualenv
  2. Manages the virtual environment directory in pyenv
  3. The virtual environment can be used (activates) by a mechanism such as pyenv local.

However, there is a caveat about this number 3. rbenv, pyenv, etc. use a mechanism called shims to use multiple versions (including virtual environments) properly.

To explain shims roughly, collect the command names under the bin / directory from all versions, and prepare a shell script with the same name in $ PYENV_ROOT / shims. The shell script is supposed to run the pyenv exec command name.

Managing the virtual environment with this mechanism means that commands in the virtual environment, such as those executed with the bundle exec command name in Bundler, will also be in shims and can be accessed in the PATH. That is. Commands provided by libraries installed only in a virtual environment for a project are always in the PATH, appear in TAB key completion, and give an error when executed. (For example, pyenv: pygmentize: command not found).

In short, the convenience of pyenv-virtualenv comes at the cost of "quarantine commands pollute the global PATH". However, if you do pyenv uninstall virtual environment name, commands that are unique to that virtual environment will be removed from shims, so it is quite possible to gradually stop pyenv-virtualenv after the disadvantages actually become a problem. So I don't think you need to be so scared.

alternative to pyenv-virtualenv

Here's a quick introduction to alternative tools that you can use if you don't use pyenv-virtualenv. Please search separately for specific usage of each tool.

direnv

direnv is a tool that allows you to customize environment variables as you move in and out of your project's directories.

You can replace the latter of the "virtual environment management" and "auto-activate" functions provided by pyenv-virtualenv. For example, if you write in .envrc as follows, it will automatically activate the virtual environment called venv in that directory.

.envrc


source venv/bin/activate

Not limited to Python, it is convenient for Go developers to use it for general purposes, such as changing the GOPATH for each project.

Use venv directly

The first choice is to use venv directly as described above (“Differences between Bundler and venv”) without using virtual environment management tools such as virtualenvwrapper and pew described below.

This is the closest to the usability of rbenv + Bundler, so I think it's easy to understand. If you need automatic activation of your virtual environment, you can use the direnv introduced above.

Unfortunately, compared to Bundler, there are no standards or de facto standards for virtual environment directory names like vendor / bundle or node_modules. You or your team must decide which one to use, such as venv, .venv, vendor / venv.

virtualenvwrapper

virtualenvwrapper is a virtual environment management tool that has long been used by heavy Python developers.

You can create, delete, or activate a virtual environment in the directory specified by the environment variable WORKON_HOME (or $ HOME / .virtualenvs`` if not specified).

pew

pew is similar to virtualenvwrapper, but uses its own implementation rather than the command provided by venv to activate the virtual environment. Specifically, instead of customizing the current shell, run the customized shell as a child process. You can return to the original environment by closing the child shell with Ctrl-D instead of the deactivate command.

If you install pew, a tool called pythonz, which builds and manages multiple versions of Python that conflicts with pyenv, will be installed as a dependency, but since the update is slower than pyenv, you can use pyenv without worrying about it. think.

pipenv

A new, easy-to-use tool like Bundler. Instead of the requirements file used by pip, use a more sophisticated TOML-based file called Pipfile to manage your library. Note that Pipfile is still an experimental tool, and the format may change in the future, so you need to be prepared for it. (I don't think it changes that often)

By default, pew is used to manage the virtual environment, but if you set PIPENV_VENV_IN_PROJECT = true and the environment variable, the .venv directory under the project will be used, so Bundler's I think it will be closer to usability.

How to use pyenv only to build Python

If you don't want to use pyenv version switching features such as pyenv local, you can find `ʻecho'eval in pyenv installation instructions You can make the shell lighter and not use shims by omitting "$ (pyenv init-)"'>> ~ / .bash_profile. If you omit this step, pyenv install, pyenv uninstall, pyenv versions`` will work fine.

Instead of pyenv global, it's a good idea to go directly into your PATH for your Python version.

$ echo 'export PATH=$PYENV_ROOT/versions/3.6.1/bin:${PATH}' >> ~/.bash_profile

If you're addicted, you can make your regular Python a virtual environment to keep the Python built by pyenv clean.

$ $PYENV_ROOT/versions/3.6.1/bin/python -m venv ~/local/python-default
$ echo 'export PATH=$HOME/local/python-default/bin:${PATH}' >> ~/.bash_profile

Recommended Posts

What Rubyist should know when using pyenv
What I got into when using Tensorflow-gpu
What Every Programmer Should Know About Memory
What Emacs users should know when writing python code in Sublime Text
What are you using when testing with Python?
Installation method when using RealSense from Python (pyenv edition)
Causes when python version cannot be changed using pyenv
Tips you should know when programming competitive programming with Python2
Minimum memo when using Python on Mac (pyenv edition)
What I was addicted to when using Python tornado
Summary when using Fabric
Precautions when using Chainer
What I was asked when using Random Forest in practice
List of libraries to install when installing Python using Pyenv