我希望我的Python脚本检测版本并在不匹配时优雅退出

4 投票
6 回答
7254 浏览
提问于 2025-04-15 19:56

我想尽量让它通用一些,比如说能兼容尽可能多的版本。

因为版本3和版本2不兼容,所以我想确保我使用正确的打印语句。

如果你有问题,请告诉我,也欢迎分享与动态逻辑相关的知识,比如可用的库。

假设我有一个脚本,它只能在版本1.x、2.x或3.x下运行。

或者一个脚本需要库A或库B。

谢谢!

编辑:

现在说到Python(和.Net不一样),一些库像SciPy和Google App Engine会让你固定在某个特定版本上。在Linux和Mac OS上,你可以在命令行中切换不同的Python版本。这就是我想避免混淆的原因——我想记住哪个脚本是针对哪个Python版本的,以及它需要哪些库。我宁愿让它以一种人类可读的方式失败。

6 个回答

8

为了避免语法错误,如果你想在Python 2和3之间混合使用语法,你需要使用条件导入。

# just psuedocode
if version is x:
   import lib_x # contains version x implementation
else:
   import lib_y # contains version y compatible implementation

不过,不建议你尝试保持Python 3和旧版本之间的兼容性。尽管如此,这里有几种方法可以检测你正在使用的Python版本:

虽然这个方法对人来说不太友好,但sys.hexversion可以在各种Python版本中使用,因为它早在1.5.2版本就已经加入了:

import sys
if sys.hexversion == 0x20505f0:
    print "It's version 2.5.5!"

你也可以通过sys.version_info获取版本信息(这个在Python 2.0中加入的):

import sys
if sys.version_info[0] == 2:
    print "You are using version 2!"
else:
    print "You are using version 1, because you would get SyntaxErrors if you were using 3!"

另外,你还可以使用platform模块,虽然这个是在Python 2.3中引入的,所以在更旧的版本中是不可用的(假设你还关心这些旧版本的话):

try:
    import platform
    if platform.python_version().startswith('2'):
        print "You're using python 2.x!"
except ImportError, e:
    print "You're using something older than 2.3. Yuck."
9

sys模块里也包含了版本信息(在2.0版本中首次提供):

import sys

if sys.version_info[0] == 2:
    print("You are using Python 2.x")
elif sys.version_info[0] == 3:
    print("You are using Python 3.x")
3
  • 如果你想维护一个同时能在Python 2和3上运行的代码库,你不会试图写出能在两者上都能运行的代码,因为那样会很麻烦、很丑,而且容易出错。你应该先用Python 2写代码,然后用2to3工具来转换成Python 3的代码。(你也可以用Python 3写代码,然后用3to2来转换,但我觉得那个工具不够成熟。)2to3虽然不是完美的,但写出能被它转换的Python 2代码,比写出能在Python 3解释器上直接运行的Python 2代码要合理得多。

    编辑:这在2010年是个常识,但后来发现并不是这样。现在的做法是写一个多语言兼容的代码。2to3最终并没有那么有用。
  • 另一个选择是Cython,这是一种类似Python的语言,可以用来创建C扩展模块。Cython模块可以同时在Python 2和3中使用。

  • 当你需要支持多个版本的Python时,通常直接检查你想要的功能是否可用,比单纯检查版本号要好。直接检查版本号比较脆弱,也不够直接。

    举个例子,如果我想要一些能在Python 2.5之前运行的代码,我会这样写:

    try: 
        any
    except NameError:
        def any(iterable):
            for item in iterable:
                if item:
                    return True
            return False
    

    (注意,这几乎是捕获NameError的唯一原因。)同样,库的可用性也可以通过捕获ImportError来检查。编辑:现在有很多工具可以帮助你简化这个过程。

  • 如果你想让一个脚本记住它是哪个版本的,就像你说的,根本不需要尝试支持多个版本。直接在脚本的开头加上正确的版本号,然后根据这个来运行脚本就可以了。

撰写回答