首页 > 解决方案 > 检查包含较新语法的包 __init__.py 中的 Python 版本

问题描述

在我的程序中检查Python版本一般是没有问题的,但是如果使用语法,老解释器不知道的一般怎么做呢?

__init__.py在子目录/包中考虑以下内容foo

import sys

__version__ = '0.1'

try:
    if sys.version_info[:2] < (3,8):
        print("you're doomed")
    else:
        print("you're fine")

    print(f"{__version__=}")
    
except SyntaxError:
    print("why is this line not reached on importing?")

print("here we go")

现在,当尝试导入该包时,会出现 SyntaxError:

$ python3
Python 3.7.7 (default, Apr  1 2020, 13:48:52) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<fstring>", line 1
    (__version__=)
                ^
SyntaxError: invalid syntax
>>> 

或直接使用:

$ python3 foo/__init__.py                                                                                       /dev/shm |myself@mydesk|0|11:53:43 
  File "<fstring>", line 1
    (__version__=)
                ^
SyntaxError: invalid syntax

尽管我试图捕获异常(如果没有相应行,这对于 SyntaxError 当然是不可能的eval),如果解释器版本低于 3.8,Python 甚至不会运行该文件,因为新的 f-string ' =' 说明符是用过的。(在这个最小的例子中,有人可能会建议把它放在一边,但在我的真实包中,它被用于许多地方,包括许多子包的 __init__.py;尤其是为了简化日志记录。)

那么我们如何确保在这样的场景中正确的最低 Python 版本,使用新的语法,包括给用户的警告消息?

标签: python

解决方案


我能想到的最简单的解决方案是不放入特定于版本的语法__init__.py以确保它始终可以被解析。

import sys

__version__ = '0.1'

if sys.version_info[:2] < (3,8):
    raise RuntimeError("You're doomed.")

from .baz import quux
from .hernekeitto import teline

这个文件总是可以被解析和执行......基本上是从 2.7 开始的任何 Python,并且由于导入是运行时的,因此程序只会开始崩溃一次baz.pyhernekeitto.py使用深奥的语法。


推荐阅读