如何优雅地处理由于旧的解释器版本而导致的失败的未来function(__future__)导入?

你如何优雅地处理失败的未来function导入? 如果用户使用Python 2.5运行,并且模块中的第一条语句是:

from __future__ import print_function 

编译Python 2.5的这个模块将失败,出现:

  File "__init__.py", line 1 from __future__ import print_function SyntaxError: future feature print_function is not defined 

我想通知用户,他们需要重新运行Python> = 2.6的程序,也许提供一些如何操作的说明。 但是,引用PEP 236 :

在future_statement之前可能出现的唯一行是:

  • 模块docstring(如果有的话)。
  • 注释。
  • 空白行。
  • 其他future_statements。

所以我不能这样做:

 import __future__ if hasattr(__future__, 'print_function'): from __future__ import print_function else: raise ImportError('Python >= 2.6 is required') 

因为它产生:

  File "__init__.py", line 4 from __future__ import print_function SyntaxError: from __future__ imports must occur at the beginning of the file 

PEP的这个片段似乎给了它内联的希望:

问:我想在try / except块中包装future_statements,所以我可以根据运行的Python版本使用不同的代码。 为什么我不能?

A:对不起! 尝试/除了是一个运行时function; future_statements主要是编译时噱头,而你的try / except在编译器完成后很久就会发生。 也就是说,当你尝试/除了,模块的语义已经完成了。 由于try / except不能完成它看起来应该完成的事情,所以根本不允许。 我们也希望保持这些特别声明很容易被发现和承认。

请注意,您可以直接导入__future__,并使用sys.version_info中的信息来确定您正在运行的版本的位置与给定要素的状态有关。

想法?

“我想通知用户,他们需要用Python> = 2.6重新运行程序,并且可能会提供一些关于如何这样做的说明。”

这不是什么一个自述文件?

这是你的select。 一个“包装器”:在运行目标之前检查环境的一小块Python。

文件:appwrapper.py

 import sys major, minor, micro, releaselevel, serial = sys.version_info if (major,minor) <= (2,5): # provide advice on getting version 2.6 or higher. sys.exit(2) import app app.main() 

什么是“直接import”的意思。 您可以检查__future__的内容。 你仍然受到from __future__ import print_function的信息给编译器的限制,但是在导入完成真正的工作的模块之前,你可以四处search。

 import __future__, sys if hasattr(__future__, 'print_function'): # Could also check sys.version_info >= __future__. print_function.optional import app app.main() else: print "instructions for upgrading" 

我之前使用的一个相当简单而又简单的方法是利用在Python 2.6中引入字节文字的事实,并在文件的开头附近使用类似的东西:

 b'This module needs Python 2.6 or later. Please do xxx.' 

这在Python 2.6或更高版本中是无害的,但在任何早期版本中都是SyntaxError 。 任何人试图编译你的文件仍然会得到一个错误,但他们也得到你想要给的任何消息。

你可能会认为你必须from __future__ import print_function之后得到这一行,那么这将是生成SyntaxError的导入,你不会看到有用的错误信息,但奇怪的是后面的错误优先。 我怀疑,由于导入的错误本身并不是一个真正的语法错误,所以在第一次编译过程中不会引发这个错误,所以真正的语法错误首先被提出(但是我猜测)。

这可能不符合你的“优雅”的标准,它是Python 2.6的特定版本,但它快速而容易。

只需在"from __future__ import ..."的同一行添加注释,如下所示:

 from __future__ import print_function, division # We require Python 2.6 or later 

由于Python显示包含错误的行,如果您尝试使用Python 2.5运行模块,您将得到一个很好的描述性错误:

  from __future__ import print_function, division # We require Python 2.6 or later SyntaxError: future feature print_function is not defined