Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with multiple python versions when python files have to use #!/bin/env python

Tags:

python

shebang

I have this problem:

System A runs Ubuntu and needs Python 2.6 for a bunch of different things.
I Installed Python 2.7 separately on System A
System B has Python 2.7 natively.

I have a python script BLAH which says #!/bin/env python up top.
Further down it executes another script SIGH, which up top also says: #!/bin/env python.

BLAH needs to run on either System A or System B, and it always needs to run Python 2.7

----
Part of my solution so far:
Have a wrapper script that first tries to see if which python is pointing to Python 2.7
If that's okay then run BLAH with that path for python.
Else try which python2.7 and use that path to run BLAH , and add that path to env PATH.

Problem with this solution is:

On System A (which has Python 2.7 installed separately)
When BLAH executes, it runs with Python 2.7 because of the wrapper script I wrote (okay so far..)
When BLAH spawns SIGH, SIGH uses the shebang to find python in the path and then it's in trouble because it's looking for python in env's PATH and it should be looking for python2.7 in the path.

Is there a clean way of handling this problem?

Thanks in advance!

like image 935
dana Avatar asked Jul 03 '12 21:07

dana


3 Answers

If you have a script that needs a certain python version, for example 2.7, I'd change the first line to

#!/bin/env python2.7

And then ensure that python2.7 is on your path (you may have to add symlinks as appropriate). In all the distributions I've used, these symlinks already exist.

(In fact, python is typically a symlink to pythonX which is a symlink to pythonX.Y or, in my case, python -> python2 -> python2.7. )

There's no need to hard-code a full path, as this may vary from distro to distro or box to box.

But since there should be no ambiguity for an executable on your path named python2.7, you should be fine without having to worry about hard-coding paths.

Alternatively, from within the first script, you could call the python interpreter directly, as in:

subprocess.Popen(['pythonX.Y', SCRIPT_NAME])

instead of

subprocess.Popen([SCRIPT_NAME])

EDIT As J.F. Sebastian notes in the comments, you could use sys.executable in the first argument to ensure that the second script was passed to the same interpreter as the first. e.g

subprocess.Popen([sys.executable, SCRIPT_NAME])

As a side note, that may or may not be useful, you can access the version of the "current" Python interpreter inside the script by

import sys
print(sys.hexversion)

which may be useful to determine whether the correct interpreter is running.

like image 124
jedwards Avatar answered Sep 19 '22 15:09

jedwards


What I would do is to first change the #!/bin/env to the python2.7 path directly, for example: #!/usr/local/bin/python2.7 will work.

In the case System A and B python2.7 path are in different places (which seems to be your case) you can always create a symlink like this:

ln -s /bin/python2.7 /usr/local/bin/python2.7

and it should work just fine.

like image 27
Hassek Avatar answered Sep 21 '22 15:09

Hassek


Why not use virtualenv? It allows you to use any python version installed (besides other stuff)...

starenka /tmp % virtualenv test -ppython2.6
Running virtualenv with interpreter /usr/bin/python2.6
New python executable in test/bin/python2.6
Also creating executable in test/bin/python
Installing setuptools............................done.
Installing pip...............done.

starenka /tmp % source test/bin/activate

(test)starenka /tmp % which python
/tmp/test/bin/python

(test)starenka /tmp % python --version
Python 2.6.8

(test)starenka /tmp % echo '#!/usr/bin/env python\nimport sys; print sys.version_info' > test/test.py

(test)starenka /tmp % chmod +x test/test.py

(test)starenka /tmp % test/test.py
(2, 6, 8, 'final', 0)

starenka /tmp % virtualenv test7 -ppython2.7
Running virtualenv with interpreter /usr/bin/python2.7
New python executable in test7/bin/python2.7
Also creating executable in test7/bin/python
Installing setuptools............done.
Installing pip...............done.
starenka /tmp % source test7/bin/activate

(test7)starenka /tmp % which python
/tmp/test7/bin/python

(test7)starenka /tmp % python --version
Python 2.7.3rc2

(test7)starenka /tmp % echo '#!/usr/bin/env python\nimport sys; print sys.version_info' > test7/test.py

(test7)starenka /tmp % chmod +x test7/test.py

(test7)starenka /tmp % test7/test.py
sys.version_info(major=2, minor=7, micro=3, releaselevel='candidate', serial=2)
like image 32
starenka Avatar answered Sep 21 '22 15:09

starenka