0

From PEP-370:

user script directory

A directory for binaries and scripts. [10] It's shared across Python versions and the destination directory for scripts.

Unix (including Mac)

  ~/.local/bin

Windows

  %APPDATA%/Python/Scripts

Why does it propose version-specific user site dirs but not user script dirs? Wouldn't scripts coming from different python versions conflict each other then?

Edit. Yes, they would. I did a test with python2-pytest and python3-pytest. When installing both into user dir with pip, one pytest script overwrote another without a warning.

There seems to be a relevant link but it's dead:

Discussion about the bin directory http://permalink.gmane.org/gmane.comp.python.devel/91095

Cyker
  • 9,946
  • 8
  • 65
  • 93
  • Because scripts are executables, just like other things in `/usr/bin/` and `/usr/local/bin`, etc. – Martijn Pieters Oct 30 '18 at 10:39
  • Related: [Why did this program install into ~/.local/bin ... thats the first time I have seen that happen?](//unix.stackexchange.com/q/240037) – Martijn Pieters Oct 30 '18 at 10:43
  • You can edit scripts to use a specific python executable. Just change the shebang line at the top of the script. There could still be some library conflicts, though. – Håken Lid Oct 30 '18 at 10:44
  • @MartijnPieters Executable or not, you can still have version-specific dirs under `~/.local/bin` just like with `~/.local/lib`. – Cyker Oct 30 '18 at 10:44
  • 1
    Basically, '.local/bin` is [part of the systemd home-dir filesystem spec](https://www.freedesktop.org/software/systemd/man/file-hierarchy.html#Home%20Directory), so a good choice to put local binaries and commands. There is no provision for python-specific versions. – Martijn Pieters Oct 30 '18 at 10:45
  • @HåkenLid: they already will use a specific Python version, that's not the point. Cyker is concerned about multiple Python versions with the same script. – Martijn Pieters Oct 30 '18 at 10:46
  • Well. It's pretty common for python executable scripts to have `!# /usr/bin/env python` as shebang. That could resolve to different python versions when using virtual environments. – Håken Lid Oct 30 '18 at 10:49
  • 1
    @HåkenLid: this is specifically about automated installs with `pip`, where `setup.py` console scripts entries are generated and will use a specific Python binary. – Martijn Pieters Oct 30 '18 at 10:53

1 Answers1

2

The shell doesn't support per-Python-version binaries. There is a single namespace for command-line executables, the first name found in the directories listed on PATH is used.

The point of the ~/.local/bin directory here is that it is added to the PATH environment variable, and that scripts and other executables are put there for command line use. And because there is only a single namespace for such executables, there is no point in putting commands into per-version directories here.

Instead, it is up to the project to provide you with versioned executables. The pip project uses setup.py configuration to pip, pipX and pipX.Y scripts when installed with Python X.Y, and so you'll always have a more specific version of the script when there are multiple Python versions. And you can also use the module as a script with pythonX.Y -m pip. Lots of Python command-line tools have similar support.

As for the lost GMane link (still available on the web archive); there are other archives of the Python-dev discussion still available, such as this grokbase.com rendering of the same post; that discussion was about what directory to place the scripts in, ~/bin or ~/.local/bin, and was never about per-Python-version directories.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Comparing `~/.local/bin` with `/usr/bin` sounds valid. But `/usr/bin` is often managed by system package manager while `~/.local/bin` runs wild. I just tested with `python2-pytest` and `python3-pytest`. One `pytest` script does overwrite another without warning. So I think `pythonX.Y -m` is the rescue in such case. But considering other programs install into paths like `~/.gem/ruby/1.9.1/bin`, it might be good if python some day uses a similar approach. There is no package manager for `~/.local/bin` anyway. It's better for users themselves to decide what are linked there. – Cyker Oct 30 '18 at 11:11
  • You should compare `~/.local/bin` with `/usr/local/bin`, really, as both are outside of the system package manager responsibilities. And Python has virtualenv and Pipenv to manage per-project dependencies, where Pipenv knows how to re-use virtualenvs as needed. That gives you similar behaviour as Gem does. It is not Ruby that creates those `~/.gem` directories, after all. – Martijn Pieters Oct 30 '18 at 11:19
  • Yup that's more accurate, but `/usr/local/bin` usually has root permission so things are less likely messed up. `virtualenv` actually provides best isolation, but you have to activate before each use and that's terrible for commonly used commands. I'd better ignore `~/.local/bin` and go with `pythonX.Y -m` if a package is installed with multiple versions of python. Hopefully some day they would do `~/.python/X.Y.Z/bin`. – Cyker Oct 30 '18 at 11:28
  • @Cyker: you don't have to activate a virtualenv. You can add the virtualenv-managed `/bin` directory to your path, or symlink the scripts into a directory that's on your path. – Martijn Pieters Oct 30 '18 at 12:07
  • (And what Gem does is pick which `~/.gem/ruby/*/bin` directory is on your `PATH`, nothing more, which limits you to *one ruby version for all your tools*. Gem / Ruby made a different tradeoff from Python / virtualenv / Pipenv). – Martijn Pieters Oct 30 '18 at 12:08