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

时间:2009-01-15 08:45:28

标签: python version

如果我有一个至少需要特定的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

(引导同事。)

18 个答案:

答案 0 :(得分:107)

您可以使用eval进行测试:

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

此外,Python 2.5中提供了with ,只需添加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 *

答案 1 :(得分:103)

在你的程序周围有一个包装器,它可以执行以下操作。

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."

如果你计划遇到使用2.0之前的Python解释器的人,你也可以考虑使用sys.version(),但是你有一些正则表达式要做。

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

答案 2 :(得分:31)

尝试

import platform
platform.python_version()

应该给你一个像“2.3.1”这样的字符串。如果这不是您想要的,那么通过“平台”内置提供了丰富的数据集。你想要的应该在某个地方。

答案 3 :(得分:22)

执行此版本比较的最佳方法可能是使用sys.hexversion。这很重要,因为比较版本元组不会在所有python版本中提供所需的结果。

import sys
if sys.hexversion < 0x02060000:
    print "yep!"
else:
    print "oops!"

答案 4 :(得分:15)

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")

答案 5 :(得分:9)

  

来自Nykakin的AskUbuntu答案:

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

有两个功能:

  • platform.python_version()(返回字符串)。
  • platform.python_version_tuple()(返回元组)。

Python代码

  

创建一个文件,例如: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')

使用CGI通过Windows 10上的WAMP服务器输出Python:

Screenshot 2016-11-16 14.39.01 by Suriyaa Kudo

有用的资源

答案 6 :(得分:7)

集成为Python 2.4中核心语言的一部分,以保持向后兼容。那时我做了这个,这对你也有用:

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

答案 7 :(得分:7)

虽然问题是: 如何及早获得控制权以发出错误消息并退出

我回答的问题是: 如何及早获得控制权以在启动应用之前发出错误消息

我能以与其他帖子不同的方式回答它。 到目前为止似乎是在Python中解决你的问题。

我说,在启动Python之前进行版本检查。我看到你的路径是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

这不会运行应用程序的任何部分,因此不会引发Python异常。它不会创建任何临时文件或添加任何OS环境变量。由于版本语法规则不同,它不会将您的应用程序结束为异常。这是三个不太可能的安全访问点。

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

答案 8 :(得分:3)

import sys
sys.version

会得到这样的答案

  

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

此处 2.7.6 是版本

答案 9 :(得分:2)

如上所述,语法错误发生在编译时,而不是在运行时。虽然Python是一种“解释语言”,但Python代码实际上并不是直接解释的;它被编译为字节代码,然后被解释。导入模块时会发生编译步骤(如果没有.pyc或.pyd文件形式的已编译版本),那就是当你收到错误时,而不是(非常确切地说)你的代码正在运行。

如上所述,你可以推迟编译步骤并在运行时为单行代码实现,如果你愿意,可以使用eval,但我个人更愿意避免这样做,因为它会导致Python执行可能不必要的运行时编译,对于一件事,另一件事,它创造​​了我感觉像代码混乱。 (如果你愿意,你可以生成生成代码的代码,生成代码 - 并且在6个月内完成修改和调试的绝佳时间。)所以我推荐的是更像这样的东西:

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

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

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

这样的代码
value = 'yes' if MyVarIsTrue else 'no'

..它确实支持像

这样的代码
value = MyVarIsTrue and 'yes' or 'no'

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

答案 10 :(得分:2)

将以下内容放在文件的最顶部:

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...

答案 11 :(得分:1)

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

例如:

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

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

答案 12 :(得分:1)

对于独立 python脚本,以下用于增强python版本(此处为v2.7.x)的模块docstring技巧适用(在* 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有依赖性。有关背景,请参见here

答案 13 :(得分:1)

我在快速搜索后发现了这个问题,同时尝试自己解决问题,并根据上述一些建议提出了混合搜索。

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

我认为它应该适用于2.5及以上。到目前为止,我在Linux上测试了2.66,2.7.0和3.1.2,在OS X上测试了2.6.1。

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") )

是的,我知道最终的解码/剥离线很糟糕,但我只想快速获取版本号。我要改进它。

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

答案 14 :(得分:0)

您可以查看sys.hexversionsys.version_info

sys.hexversion不是非常人性化的,因为它是十六进制数字。 sys.version_info是一个元组,所以它更加人性化。

使用sys.hexversion检查Python 3.6或更高版本:

import sys, time
if sys.hexversion < 0x30600F0:
    print("You need Python 3.6 or greater.")
    for _ in range(1, 5): time.sleep(1)
    exit()

使用sys.version_info检查Python 3.6或更高版本:

import sys, time
if sys.version_info[0] < 3 and sys.version_info[1] < 6:
    print("You need Python 3.6 or greater.")
    for _ in range(1, 5): time.sleep(1)
    exit()

sys.version_info更加人性化,但需要更多角色。我会推荐sys.hexversion,即使它不太人性化。

我希望这能帮到你!

答案 15 :(得分:0)

我在扩展akhan的出色答案,该答案甚至在Python脚本被编译之前打印出一条有用的消息。

如果要确保该脚本正在使用Python 3.6或更高版本运行,请将这两行添加到Python脚本的顶部:

#!/bin/sh
''''python3 -c 'import sys; sys.exit(sys.version_info < (3, 6))' && exec python3 -u -- "$0" ${1+"$@"}; echo 'This script requires Python 3.6 or newer.'; exit 1 # '''

(注意:第二行以四个单引号开头,以三个单引号结尾。这看起来很奇怪,但这不是一个错字。)

该解决方案的优势在于,如果使用的Python版本早于3.6,则print(f'Hello, {name}!')之类的代码不会引起SyntaxError。您会看到以下有用的消息:

This script requires Python 3.6 or newer.

当然,此解决方案仅适用于类Unix的shell,并且仅在直接调用脚本(例如:./script.py)且设置了适当的eXecute权限位时才适用。

答案 16 :(得分:-2)

这个怎么样:

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

答案 17 :(得分:-3)

问题很简单。您检查的版本是否 小于 2.4,不小于 或等于 。因此,如果Python版本是2.4,它不低于2.4。 你应该拥有的是:

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

,而不是

    if sys.version_info < (2, 4):