首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >shebang env首选python版本

shebang env首选python版本
EN

Stack Overflow用户
提问于 2013-09-24 22:52:07
回答 5查看 5.8K关注 0票数 15

我有一些python-2.x脚本,我在不同的系统之间复制,Debian和Arch。Debian将python安装为'/usr/bin/python‘,而Arch将其安装为’/usr/bin/python 2‘。一个问题是,在Arch '/usr/bin/python‘上也存在引用python-3.x的问题。所以每次我复制一个文件的时候,我都要更正这个行,这有点烦人。

在拱门上我用

代码语言:javascript
复制
#!/usr/bin/env python2

当我在debian的时候

代码语言:javascript
复制
#!/usr/bin/env python

既然Debian上不存在'python2‘,那么有没有办法传递一个首选的应用程序呢?或许可以做一些壳的扩张?例如,我不介意它是否取决于'/bin/sh‘的存在。下面的内容很好,但不管用。

代码语言:javascript
复制
#!/usr/bin/env python2 python
#!/usr/bin/env python{2,}
#!/bin/sh python{2,}
#!/bin/sh -c python{2,}

令人沮丧的是,'sh -c python{2,}‘在命令行上工作:也就是说,它在可用的地方调用python2,否则调用python2。

我不希望在Debian上创建一个链接‘python 2->python’,因为如果我将脚本交给其他人,它就不会运行。我也不想让'python‘指向Arch上的python2,因为它会随着更新而中断。

有没有一种不需要编写包装器就能做到这一点的干净方法?

我知道以前也有人问过类似的问题,但我没有看到任何符合边界条件的答案:) Conditional shebang line for different versions of Python

-更新

我黑了一个丑陋的外壳解决方案,这是目前的工作。

代码语言:javascript
复制
#!/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

说明:获取版本号(v是bash数组)并检查

代码语言:javascript
复制
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

使用stdin (-)和pass参数($*)输入的已找到的程序$*

代码语言:javascript
复制
$p - $* <<EOF
...
EOF
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-09-26 09:38:16

代码语言:javascript
复制
#!/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

这首先以shell脚本的形式运行。您几乎可以在''''# '''之间放置任何shell代码。这样的代码将由shell执行。然后,当python在文件上运行时,python会忽略这些行,因为它们看起来就像python中的三引号字符串。

shell脚本用which python2 >/dev/null测试路径中是否存在二进制文件,然后执行它(所有参数都在正确的位置)。有关此问题的更多信息,请参见Why does this snippet with a shebang #!/bin/sh and exec python inside 4 single quotes work?

注意:行以四个'开头,它们在第四个'和shell命令的开始之间必须没有空格(which.)

票数 22
EN

Stack Overflow用户

发布于 2013-09-25 00:15:57

就像这样:

代码语言:javascript
复制
#!/usr/bin/env python
import sys
import os
if sys.version_info >= (3, 0):
    os.execvp("python2.7", ["python2.7", __file__])
    os.execvp("python2.6", ["python2.6", __file__])
    os.execvp("python2", ["python2", __file__])
    print ("No sutable version of Python found")
    exit(2)

下面的更新是一个更健壮的版本。

代码语言:javascript
复制
#!/bin/bash

ok=bad
for pyth in python python2.7 python2.6 python2; do
  pypath=$(type -P $pyth)
  if [[ -x $pypath ]] ; then
    ok=$(
      $pyth <<@@

import sys 
if sys.version_info < (3, 0):
  print ("ok")
else:
  print("bad")
@@

    )
    if [[ $ok == ok ]] ; then
      break
    fi
  fi
done

if [[ $ok != ok ]]; then
  echo "Could not find suitable python version"
  exit 2
fi

$pyth <<@@
<<< your python script goes here >>>
@@
票数 1
EN

Stack Overflow用户

发布于 2016-03-02 10:26:50

我会把这个留在这里供将来参考。

我自己的所有脚本通常都是为Python 3编写的,所以我使用Aaron McDaid的答案的修改版本来检查Python 3,而不是2:

代码语言:javascript
复制
#!/usr/bin/env sh
''''which python3 >/dev/null 2>&1 && exec python3 "$0" "$@" # '''
''''test $(python --version 2>&1 | cut -c 8) -eq 3 && exec python "$0" "$@" # '''
''''exec echo "Python 3 not found." # '''

import sys
print sys.argv
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18993438

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档