如果我有一个至少需要特定的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
(引导同事。)
答案 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()
(返回元组)。创建一个文件,例如:
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:
答案 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.hexversion
或sys.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):