如果我有一个Python脚本,至少需要一个特定的 在Python版本中,优雅地失败的正确方式是什么 当使用早期版本的Python启动脚本时?

如何尽早获得控制权以发出错误消息 并退出吗?

For example, I have a program that uses the ternery operator (new in 2.5) and "with" blocks (new in 2.6). I wrote a simple little interpreter-version checker routine which is the first thing the script would call ... except it doesn't get that far. Instead, the script fails during python compilation, before my routines are even called. Thus the user of the script sees some very obscure synax error tracebacks - which pretty much require an expert to deduce that it is simply the case of running the wrong version of Python.

我知道如何检查Python的版本。问题是一些语法在旧版本的Python中是非法的。考虑这个程序:

import sys
if sys.version_info < (2, 4):
    raise "must use python 2.5 or greater"
else:
    # syntax error in 2.4, ok in 2.5
    x = 1 if True else 2
    print x

当在2.4下运行时,我想要这个结果

$ ~/bin/python2.4 tern.py 
must use python 2.5 or greater

而不是这个结果:

$ ~/bin/python2.4 tern.py 
  File "tern.py", line 5
    x = 1 if True else 2
           ^
SyntaxError: invalid syntax

(为同事通灵。)


当前回答

import sys
sys.version

会得到这样的答案吗

'2.7.6(默认,2016年10月26日,20:30:19)\n[GCC 4.8.4]'

这里是2.7.6版本

其他回答

这个怎么样:

import sys

def testPyVer(reqver):
  if float(sys.version[:3]) >= reqver:
    return 1
  else:
    return 0

#blah blah blah, more code

if testPyVer(3.0) == 1:
  #do stuff
else:
  #print python requirement, exit statement
import sys
sys.version

会得到这样的答案吗

'2.7.6(默认,2016年10月26日,20:30:19)\n[GCC 4.8.4]'

这里是2.7.6版本

你可以使用eval进行测试:

try:
  eval("1 if True else 2")
except SyntaxError:
  # doesn't have ternary

此外,with在Python 2.5中可用,只需从__future__ import with_statement中添加。

编辑:为了尽早获得控制权,你可以将它分割成不同的.py文件,并在导入前检查主文件的兼容性(例如在包中的__init__.py中):

# __init__.py

# Check compatibility
try:
  eval("1 if True else 2")
except SyntaxError:
  raise ImportError("requires ternary support")

# import from another module
from impl import *

我认为最好的方法是测试功能而不是版本。在某些情况下,这是微不足道的,但在另一些情况下并非如此。

eg:

try :
    # Do stuff
except : # Features weren't found.
    # Do stuff for older versions.

只要你在使用try/except块时足够具体,你就可以覆盖大部分基础。

对于独立的python脚本,下面的模块docstring技巧可以强制使用python版本(这里是v2.7.x)(在*nix上测试)。

#!/bin/sh
''''python -V 2>&1 | grep -q 2.7 && exec python -u -- "$0" ${1+"$@"}; echo "python 2.7.x missing"; exit 1 # '''

import sys
[...]

这应该可以处理缺少的python可执行文件,但是依赖于grep。查看这里的背景。