问题
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!
回答1:
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.
回答2:
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.
回答3:
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)
回答4:
Stupid and simple
In the shell, if needed:
ln -s /path/to/your/python2.X /usr/local/bin/python2
In the Python script:
#!/bin/bash
"exec" "python2" "$0"
I've been through this kind of problems, and this solution solved most of the cases, and was easily portable from one system to another (you could face different paths between systems, different versions of the software...). First create a symlink to ensure that you will run the right version of Python (this is specially true now that you never now if Python3 is just Python), and then rely on the bash env. So, you don't change your script every time you target a system for a util-script that doesn't call for the hassle of a package.
来源:https://stackoverflow.com/questions/11319676/dealing-with-multiple-python-versions-when-python-files-have-to-use-bin-env-p