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

本小妞迷上赌 提交于 2020-01-02 01:56:17

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!