Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

shebang env preferred python version

I have some python-2.x scripts which I copy between different systems, Debian and Arch linux. Debian install python as '/usr/bin/python' while Arch installs it as '/usr/bin/python2'. A problem is that on Arch linux '/usr/bin/python' also exists which refers to python-3.x. So every time I copy a file I have to correct the shebang line, which is a bit annoying.

On Arch I use

#!/usr/bin/env python2

While on debian I have

#!/usr/bin/env python

Since 'python2' does not exist on Debian, is there a way to pass a preferred application? Maybe with some shell expansion? I don't mind if it depends on '/bin/sh' existing for example. The following would be nice but don't work.

#!/usr/bin/env python2 python
#!/usr/bin/env python{2,}
#!/bin/sh python{2,}
#!/bin/sh -c python{2,}

The frustrating thing is that 'sh -c python{2,}' works on the command line: i.e. it calls python2 where available and otherwise python.

I would prefer not to make a make a link 'python2->python' on Debian because then if I give the script to someone else it will not run. Neither would I like to make 'python' point to python2 on Arch, since it breaks with updates.

Is there a clean way to do this without writing a wrapper?

I realize similar question have been asked before, but I didn't see any answers meeting my boundary conditions :) Conditional shebang line for different versions of Python

--- UPDATE

I hacked together an ugly shell solution, which does the job for now.

#!/bin/bash
pfound=false; v0=2; v1=6
for p in /{usr/,}bin/python*; do  
  v=($(python -V 2>&1 | cut -c 7- | sed 's/\./ /g'))
  if [[ ${v[0]} -eq $v0 && ${v[1]} -eq $v1 ]]; then pfound=true; break; fi
done
if ! $pfound; then echo "no suitable python version (2.6.x) found."; exit 1; fi
$p - $* <<EOF

PYTHON SCRIPT GOES HERE

EOF

explanation: get version number (v is a bash array) and check

v=($(python -V 2>&1 | cut -c 7- | sed 's/\./ /g'))
if [[ ${v[0]} -eq $v0 && ${v[1]} -eq $v1 ]]; then pfound=true; break; fi

launch found program $p with input from stdin (-) and pass arguments ($*)

$p - $* <<EOF
...
EOF
like image 266
jaap Avatar asked Sep 24 '13 22:09

jaap


People also ask

Is shebang required Python?

Whether using the shebang for running scripts in Python is necessary or not, greatly depends on your way of executing scripts. The shebang decides if you'll be able to run the script as a standalone executable without typing the python command. So, if you want to invoke the script directly – use the shebang.

How do you use shebang in Python 3?

A shebang line #!/usr/bin/python3 Its purpose is to define the location of the interpreter. By adding the line #!/usr/bin/python3 on the top of the script, we can run the file.py on a Unix system and automatically will understand that this is a python script. Alternative, you could run the script as python3 file.py .

What is #!/ Usr bin env python for?

If you have installed many versions of Python, then #!/usr/bin/env ensures that the interpreter will use the first installed version on your environment's $PATH. If you are using Unix, an executable file that is meant to be interpreted can indicate what interpreter to use by having a #!

How do I run a Python file in shebang?

#!/usr/bin/env python """ The first line in this file is the "shebang" line. When you execute a file from the shell, the shell tries to run the file using the command specified on the shebang line. The ! is called the "bang". The # is not called the "she", so sometimes the "shebang" line is also called the "hashbang".


1 Answers

#!/bin/sh
''''which python2 >/dev/null 2>&1 && exec python2 "$0" "$@" # '''
''''which python  >/dev/null 2>&1 && exec python  "$0" "$@" # '''
''''exec echo "Error: I can't find python anywhere"         # '''

import sys
print sys.argv

This is first run as a shell script. You can put almost any shell code in between '''' and # '''. Such code will be executed by the shell. Then, when python runs on the file, python will ignore the lines as they look like triple-quoted strings to python.

The shell script tests if the binary exists in the path with which python2 >/dev/null and then executes it if so (with all arguments in the right place). For more on this, see Why does this snippet with a shebang #!/bin/sh and exec python inside 4 single quotes work?

Note: The line starts with four ' and their must be no space between the fourth ' and the start of the shell command (which...)

like image 184
Aaron McDaid Avatar answered Oct 07 '22 00:10

Aaron McDaid