3

I often see this at the top of .py files:

#!/usr/bin/env python

With the unknown state of the OS defaults, I wonder why it's not:

#!/usr/bin/env python2
#!/usr/bin/env python3

If most OSs provide this versioned symlink, wouldn't that be better?

I found PEP 394 while looking around, which states that for the time being, developers should assume python -> python2 -> python2.x. It also states that one can assume that the versioned equivalents, python3 and python2, exist. So what's the harm in not leaving it to chance and providing that extra character?

If one doesn't have python2 installed because the OS ships by default with python -> python3 (like Arch linux), I'd much prefer this issue when running a script or program:

/usr/bin/env: ‘python2’: No such file or directory

Alternatively, this error is much worse, particularly for a new user (python exists, it's just the wrong version):

File "<stdin>", line 1
  print 'Hello world'
                    ^
SyntaxError: Missing parentheses in call to 'print'

That said, I find the latter far more common. At least now I know some typical compatibility errors well enough to think to myself "Oh, right. It's the python symlink."

Two questions ask how to specify/verify the desired version:

  • This 2010 question suggests treating python as meaning python2 and python3 as required to explicitly call out python3.

  • This 2013 question: maybe implies that python3 shouldn't be used because not all distros ship with it?

Is there an obvious reason I (or python programmers) shouldn't use a versioned env call if most OSs provide it? To use just python is seeming to cater to a minority who don't have the versioned command while causing confusion to the vast majority who do.

Maybe the answer is to use versioned commands (I'm getting that from PEP 394) but enough time hasn't elapsed to see them appear. To date I've never seen a versioned env call... then again, if it works I never look. If it breaks, it's always a version-less python line so my mental counts are probably skewed!


Some github stats on searches; I was curious on usage:

  • #!/usr/bin/env python2: ~210k python file code hits
  • #!/usr/bin/env python3: ~460k
  • #!/usr/bin/env python: ~6 million

This could mean that most code is old enough that if the recommendations of the questions above was the prevailing wisdom, folks just haven't updated their files?


I looked at these popular OSs and found them all to use versioned commands:

Hendy
  • 10,182
  • 15
  • 65
  • 71
  • 1
    You could use just `#!/usr/bin/env python` if your code is Python2/3 compatible. But I think that's a very minimal amount of code that works that way. Most of it is heritage from before Python 3, including tutorials etc that still suggest to use `/usr/bin/env python`, without warning about the consequences. –  Jul 12 '17 at 00:44
  • 1
    fwiw, the default installation of python on windows **doesn't** adhere to pep394 -- it just provides `python.exe` and `pythonw.exe` – anthony sottile Jul 12 '17 at 01:17
  • @Evert of course after I wrote this, that dawned on me :) I think I just saw an example of that with some `import __future__` stuff, and that now makes sense. Very valid that if you've written compatible code you don't need to care. – Hendy Jul 12 '17 at 02:05
  • This question is the number one reason I don't recommend anyone to learn python or use it for anything. – TamaMcGlinn Apr 23 '20 at 14:55
  • @TamaMcGlinn I hear you, but I feel like there's plenty of "learn once, never need to learn again" quirks for any language. This legit only affects deployment, so at the very least "use it for anything" is a huge overreaction (does not impact single computer use cases). Imagine someone struggling with `gdb` and debug compiler flags for the first time and then advocating no one should ever learn C. – Hendy Apr 24 '20 at 16:01
  • 1
    The problem is insidious in that it ends up on user's machines, and has no satisfactory solution. Don't get me wrong, I love python3; but we need to fix the problem that people and their machines think all python scripts are compatible with all interpreter versions. – TamaMcGlinn Apr 24 '20 at 16:37
  • @TamaMcGlinn I can dig that answer. If anything hopefully [this](https://pythonclock.org/) can make for a saner future :) – Hendy Apr 25 '20 at 01:35
  • For instance, consider [this](https://askubuntu.com/questions/767292/importerror-no-module-named-lsb-release) question; the writers of the lsb_release package have assumed that python 3.6 would be backwards compatible, which is a reasonable assumption if you know what semantic versioning is. But if you try to import the 'lsb_release' package under python3.6, you will find it missing. (it is present in python3.5) – TamaMcGlinn Apr 27 '20 at 09:48
  • I, for one, am adding `#!/bin/env python3.9` to all my python3.9 scripts, and am not assuming that it will work with python3.10. – TamaMcGlinn Jun 11 '21 at 05:57

1 Answers1

1

When you write the script, you may induce various dependencies on a particular version of Python. Use a dict comprehension? You need at least Python 2.7. Using the async keyword? You need at least Python 3.5.

When you use #!/usr/bin/env python, you aren't saying anything about which version of Python is required to execute your script; you are just saying "Use whatever version of Python is found in your path first." Fundamentally, the developer is the wrong person to specify the shebang.

Instead, the user should be setting the shebang to the path of the correct version of Python on their system.

The distutils package strikes a good compromise here. You, the developer, just put #!python in your script. When you install the script via python setup.py install, the installer replaces #!python with whatever path is correct on the target machine.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • I sort of get this... but "my system" is also a agglomeration of all the software installed on it. So, say I want to code in `python3`, my OS (arch) assumes `python == python3`, and I install software from someone ([like this](https://github.com/gepd/Deviot/issues/64)) who wrote it for v2.7. Which is "the correct" version for my system? – Hendy Jul 12 '17 at 01:58
  • Also, if the developer has an instance of `print 'blah'` in his/her code, then they *have* specified the shebang (implicitly). Part of my question is indirectly asking why software currently written/updated isn't acknowledging this (which led me to wonder if maybe there's a deeper reason than "because history was written in `python2` and that's what we've always done"). – Hendy Jul 12 '17 at 02:03
  • 1
    Not the user; the *installer* should set the hash-bang (whether the installer be a package manager, an administrator or an end-user doesn't matter). –  Jul 12 '17 at 02:14
  • @Evert Thanks, that's a good clarification. I was using "user" as a (intentionally) vague stand-in for whoever runs the package manager. – chepner Jul 12 '17 at 11:34