11

Depending on system, python==python2 or python==python3.

Executable Python scripts, starts with:

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

For python py3k it is provided in documentation I should/can use it with version number, so I do this:

#!/usr/bin/env python3

But I've found a problem with py2k scripts.

While in py2k documentation it is written to use : #! /usr/bin/env python ,

on some *nix-es python py3k is default, so python==python3. (For example ArchLinux python package , here python package files).

How to package (configure,make) and/or prepare python scripts for distribution to handle that ?

I ask about making software packages that can be run easily by users (without modyfing their environment)

Can I do the same trick for python py2k scripts as for python py3k scripts and set it as : #!/usr/bin/env python2 ? Can I be sure that each python py2k distribution contains python2 file, so #!/usr/bin/env python2 will work ?

If yes, why it is not proposed as standard, for example in python py2k documentation ?

Grzegorz Wierzowiecki
  • 13,865
  • 23
  • 89
  • 137
  • 4
    As far as i know you can always use `python2` to run it (if it installed), and alwayes you can check the version with `python -V`. if you want that `python` would be 2 or 3, you should `rm /usr/bin/python` and then create symlink that points from your desierd python version e.g `ln -s /usr/bin/python2.5 /usr/bin/python`. – Hanan Dec 11 '11 at 10:36
  • Thanks for ensuring me about `python2`. I wonder why is it not standard to use it when there is py2k and py3k and default `python` can differ. What about your advice about **removing** - it's not proper to this example, cause I ask about packaging. I'd like to make package that can run in different configurations/systems. No way about modifying environment. What about checking - it does not apply to [Shebang](http://en.wikipedia.org/wiki/Shebang_%28Unix%29) - as far As I know. – Grzegorz Wierzowiecki Dec 11 '11 at 12:45
  • I believe what @Hanan N. is trying to tell you is that if you are writing Python 2.x code, then use `#!...python2` in your programs and if you are using Python 3.x, then use `#!...python3`. Don't rely on the operating system to have the right link if you know it will only work on a specific release. I work with systems which still have Python 1.5.2 installed as `/usr/bin/python` - I either write code to handle older Python releases or use `python2`. – Arcege Dec 11 '11 at 18:07
  • @Arcege I agree with @HananN about using `#!/usr/bin/env python2`, so I've written "thanks" for that Part - I liked it. About this part, I just want to be ensured it's portable way. About second part related with `rm` I've just wanted to show it's not related with packaging but user desktop customization. – Grzegorz Wierzowiecki Dec 11 '11 at 21:27
  • 2
    @Arcege I don't have a `python2` executable on my system (Debian squeeze). `python` is a symlink to `python2.6`, and `python3` is a symlink to `python3.1`, but there is no `python2`. – Gilles 'SO- stop being evil' Dec 11 '11 at 23:07
  • 1
    [Is there a standard way to make sure a python script will be interpreted by python2 and not python3?](http://stackoverflow.com/q/3586776) – Gilles 'SO- stop being evil' Dec 11 '11 at 23:09
  • Maybe there is a "tricky" way of making shebang in order to determine,ensure it's python2 ? – Grzegorz Wierzowiecki Dec 12 '11 at 23:48
  • Question is about packaging. Maybe it's wise to include some replacement to `env`, which searches right py2k program (python2, python...)? AFAIK shebang [should not be nested](http://www.in-ulm.de/~mascheck/various/shebang/), so `env` replacement shouldn't be script, should be? Some propositions ? – Grzegorz Wierzowiecki Dec 13 '11 at 00:00

3 Answers3

3

A script can check its Python version and, if that's Python 3, re-start itself using Python 2. Add the following near the head of the script:

if sys.version > '3':
  python2 = os.popen('which python2 2> /dev/null').read().rstrip()
  if python2:
    args = sys.argv[:]
    args.insert(0,python2)
    os.execv(python2,args)
  else:
    sys.exit("%s requires Python Version 2 (python2 not in PATH)" % os.path.basename(__file__))

This uses the system's which command to locate python2 in the environment's PATH. It then relaunches itself with that (or aborts if unable to find it).

Note that the script does need to be valid Python 3 syntax for it to start in Python 3.

Also, any output should be flushed before the execv call or it will be lost. Adding, for example, sys.stdout.flush() just before the call to execv will flush any print statements.

starfry
  • 7,302
  • 6
  • 47
  • 69
1

I think the "standard" is defined in https://www.python.org/dev/peps/pep-0394/

This PEP provides a convention to ensure that Python scripts can continue to be portable across *nix systems, regardless of the default version of the Python interpreter (i.e. the version invoked by the python command).

  • python2 will refer to some version of Python 2.x.
  • python3 will refer to some version of Python 3.x.
  • for the time being, all distributions should ensure that python refers to the same target as python2.
  • however, end users should be aware that python refers to python3 on at least Arch Linux (that change is what prompted the creation of this PEP), so python should be used in the shebang line only for scripts that are source compatible with both Python 2 and 3.
  • in preparation for an eventual change in the default version of Python, Python 2 only scripts should either be updated to be source compatible with Python 3 or else to use python2 in the shebang line.
Lesmana
  • 26,889
  • 20
  • 81
  • 86
StrongBad
  • 5,151
  • 9
  • 47
  • 73
1

On older versions, there may just be python instead of python2. To make your sheebang line clearer, you could create a link python2 -> python so you can use #!/usr/bin/env python2.

DocSalvager
  • 2,143
  • 2
  • 25
  • 38
  • However, it does not solve the problem stated. Because the question is how to make your script portable enough, so it can run in all of mentioned environments (with "python" "python2" etc) – Grzegorz Wierzowiecki Aug 13 '13 at 18:37