如何在使用新语言function的程序中检查Python版本?

如果我有一个需要至less一个特定版本的Python的Python脚本,当使用较早版本的Python来启动脚本时,正确地失败的正确方法是什么?

如何及早获得控制权来发出错误信息并退出?

例如,我有一个使用ternery操作符(2.5中新增)和“with”块(2.6中新增)的程序。 我写了一个简单的小解释程序版本检查程序,这是脚本将调用的第一个东西,除非它没有那么远。 相反,脚本在python编译期间失败,甚至在我的例程甚至被调用之前。 因此,脚本的用户看到一些非常模糊的synax错误回溯 – 这非常需要专家推断,这只是运行错误版本的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 

(为同事提供渠道)

你可以使用eval来testing:

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

另外,在Python 2.5中可用,只需from __future__ import with_statement添加from __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 * 

有一个包装你的程序,执行以下操作。

 import sys req_version = (2,5) cur_version = sys.version_info if cur_version >= req_version: import myApp myApp.run() else: print "Your Python interpreter is too old. Please consider upgrading." 

你也可以考虑使用sys.version() ,如果你打算遇到使用2.0以前的Python解释器的人,但是你有一些正则expression式。

而且可能有更优雅的方法来做到这一点。

尝试

导入平台
 platform.python_version()

应该给你一个像“2.3.1”的string。 如果这不是你想要的,那么通过“平台”内置可以获得一组丰富的数据。 你想要的应该在那里。

做这个版本比较的最好方法是使用sys.hexversion 。 这是很重要的,因为比较版本元组不会给你所有python版本所需的结果。

 import sys if sys.hexversion < 0x02060000: print "yep!" else: print "oops!" 
 import sys # prints whether python is version 3 or not python_version = sys.version_info.major if python_version == 3: print("is python 3") else: print("not python 3") 

在AskUbuntu上回复Nykakin :

您也可以使用标准库中的platform模块从代码本身检查Python版本。

有两个function:

  • platform.python_version() (返回string)。
  • platform.python_version_tuple() (返回元组)。

Python代码

创build一个文件,例如: version.py

简单的方法来检查版本:

 import platform print(platform.python_version()) print(platform.python_version_tuple()) 

您也可以使用eval方法:

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

在命令行中运行Python文件:

 $ python version.py 2.7.11 ('2', '7', '11') 

在Windows 10上通过WAMP服务器的CGI输出:

截图2016-11-16 14.39.01由Suriyaa Kudo


有用的资源

虽然问题是:我如何获得足够的控制权发出错误消息并退出?

我回答的问题是:在启动应用程序之前,如何获得足够的控制权来发出错误消息?

我可以用其他的post来回答这个问题。 似乎到目前为止答案都试图解决你的问题在Python中。

我说,在启动Python之前进行版本检查。 我看到你的path是Linux或Unix。 不过,我只能为你提供一个Windows脚本。 我将其映射到linux脚本语法的映像不会太难。

这是2.7版本的DOS脚本:

 @ECHO OFF REM see http://ss64.com/nt/for_f.html FOR /F "tokens=1,2" %%G IN ('"python.exe -V 2>&1"') DO ECHO %%H | find "2.7" > Nul IF NOT ErrorLevel 1 GOTO Python27 ECHO must use python2.7 or greater GOTO EOF :Python27 python.exe tern.py GOTO EOF :EOF 

这不会运行应用程序的任何部分,因此不会引发Pythonexception。 它不创build任何临时文件或添加任何操作系统环境variables。 而且由于版本语法规则的不同,它不会将您的应用程序终止到exception。 这是三个可能的安全访问点。

“FOR / F”线是关键。 FOR / F“tokens = 1,2”%% G IN('“python.exe -V 2>&1”')DO ECHO %% H | find“2.7”> Nul

对于多个python版本,请查看url: http : //www.fpschultze.de/modules/smartfaq/faq.php? faqid =17

而我的破解版本:

[MS脚本; Python版本检查Python模块预启动] http://pastebin.com/aAuJ91FQ

集合成为Python 2.4核心语言的一部分,以保持向后兼容。 当时我做到了这一点,这也将为你工作:

 if sys.version_info < (2, 4): from sets import Set as set 

如上所述,语法错误发生在编译时,而不是运行时。 虽然Python是一种“解释型语言”,但Python代码实际上并没有直接解释; 它被编译成字节码,然后解释。 有一个编译步骤,当一个模块被导入时(如果没有.pyc或.pyd文件forms的可用编译版本),那就是当你得到你的错误,而不是(完全)你的代码正在运行。

如果你想用上面提到的eval,你可以放弃编译步骤,并在运行时为单行代码执行,但我个人更喜欢避免这样做,因为它会导致Python执行潜在的不必要的运行时编译,一方面,另一方面,它创造了我觉得像代码混乱。 (如果你愿意的话,你可以生成生成代码的代码,并在6个月内完成一个绝妙的时间修改和debugging。)所以我推荐的是更像这样的东西:

 import sys if sys.hexversion < 0x02060000: from my_module_2_5 import thisFunc, thatFunc, theOtherFunc else: from my_module import thisFunc, thatFunc, theOtherFunc 

..即使我只有一个使用新语法的函数,而且它很短,我也会这样做。 (事实上​​,我会采取一切合理的措施来减less这些函数的数量和大小,甚至可能写一个像ifTrueAElseB(cond,a,b)这样的函数。

另一件值得指出的事情(我还有点惊讶,没有人指出),虽然早期版本的Python不支持代码

 value = 'yes' if MyVarIsTrue else 'no' 

它确实支持类似的代码

 value = MyVarIsTrue and 'yes' or 'no' 

这是写三元expression的旧方法。 我还没有安装Python 3,但据我所知,“旧”的方式至今仍然有效,所以你可以自己决定是否值得有条件地使用新的语法,如果你需要的话以支持使用旧版本的Python。

把以下放在你的文件的最顶端:

 import sys if float(sys.version.split()[0][:3]) < 2.7: print "Python 2.7 or higher required to run this code, " + sys.version.split()[0] + " detected, exiting." exit(1) 

然后继续使用正常的Python代码:

 import ... import ... other code... 
 import sys sys.version 

会得到这样的答案

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

这里是2.7.6版本

我认为最好的方法是testingfunction而不是版本。 在某些情况下,这是微不足道的,而在其他情况下则不是这样。

例如:

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

只要你足够的使用try / except块,你可以覆盖大部分的基础。

我经过一个快速的search之后才发现这个问题,同时试图自己解决这个问题,并且根据上面的一些build议提出了一个混合。

我喜欢DevPlayer的使用包装脚本的想法,但缺点是,你最终维护不同的操作系统的多个包装,所以我决定在Python中编写包装,但使用相同的基本“通过运行EXE”获取版本并想出了这个。

我认为它应该在2.5以上。 我已经在Linux上的2.66,2.7.0和3.1.2以及OS X上的2.6.1上对它进行了testing。

 import sys, subprocess args = [sys.executable,"--version"] output, error = subprocess.Popen(args ,stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate() print("The version is: '%s'" %error.decode(sys.stdout.encoding).strip("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLMNBVCXZ,.+ \n") ) 

是的,我知道最终的解码/带状线是可怕的,但我只想快速获取版本号。 我会改进这一点。

这对我来说已经足够好了,但如果有人能改善它(或者告诉我为什么这是一个可怕的想法),那也太酷了。

怎么样

 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 

下面是一个快速而简单的方法,以确保如果您不符合版本要求来运行脚本,python脚本将干净地退出

 # Check python version import sys if sys.version_info < ( 3, 2): # python too old, kill the script sys.exit("This script requires Python 3.2 or newer!") # This part will only run if the version check passes print("Yay, this Python works!") 

你也可以使用这个方法为你的脚本加载交叉兼容的库。 为一个Python版本做一件事,为另一个Python版本做一件事情,限制是你的想象力。

问题很简单。 你检查版本是否小于 2.4,不小于或等于 。 所以如果Python版本是2.4,那么它不小于2.4。 你应该拥有的是:

  if sys.version_info **<=** (2, 4): 

,不

  if sys.version_info < (2, 4):