71

您如何优雅地处理失败的未来功能导入?如果用户使用 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 之前的唯一行是:

  • 模块文档字符串(如果有)。
  • 评论。
  • 空行。
  • 其他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 中的这个片段似乎给了内联执行它的希望:

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

答:对不起!try/except 是一个运行时特性;future_statements 主要是编译时的噱头,您的 try/except 会在编译器完成后很久才发生。也就是说,当您尝试/排除时,对模块有效的语义已经完成。由于 try/except 不会完成它看起来 应该完成的事情,因此根本不允许这样做。我们还希望使这些特殊声明非常易于查找和识别。

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

想法?

4

3 回答 3

60

“我想通知用户他们需要使用 Python >= 2.6 重新运行程序,并且可能会提供一些有关如何执行此操作的说明。”

这不是 README 文件的用途吗?

这是你的选择。“包装器”:在运行目标 aop 之前检查环境的一小段 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()

“直接进口”是什么意思。您可以检查__future__. 您仍然受制于 afrom __future__ import print_function是编译器的信息这一事实,但您可以在导入执行实际工作的模块之前四处寻找。

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"
于 2008-12-23T03:20:03.067 回答
47

我之前使用的一个相当老套但简单的方法是利用字节文字在 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,但它快速且容易做到。

于 2010-06-14T12:36:33.363 回答
40

只需在与 的同一行添加注释"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
于 2011-08-31T05:10:18.390 回答