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

发布于 2024-07-10 13:38:06 字数 1759 浏览 8 评论 0原文

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

from __future__ import print_function

Compiling this module for Python 2.5 will failure with a:

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

I’d like to inform the user that they need to rerun the program with Python >= 2.6 and也许提供一些有关如何执行此操作的说明。 但是,引用 PEP 236

唯一可以出现在前面的行 future_statement 是:

  • 模块文档字符串(如果有)。
  • 评论。
  • 空行。
  • 其他未来陈述。

所以我不能做类似的事情:

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 是 主要是编译时的噱头,以及 你的尝试/例外发生很久之后 编译器完成。 也就是说,由 当你尝试/除外时,语义 对模块有效的已经是 木已成舟。 由于尝试/例外 无法实现它看起来 就像它应该完成的那样,这只是 不允许。 我们也想保留 这些特殊的语句很容易 发现并识别。

请注意,您可以导入 __future__ 直接使用信息 它与 sys.version_info 一起 弄清楚你在哪里发布 运行在与a相关的立场下 给定功能的状态。

有想法吗?

How do you gracefully handle failed future feature imports? If a user is running using Python 2.5 and the first statement in my module is:

from __future__ import print_function

Compiling this module for Python 2.5 will fail with a:

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

I'd like to inform the user that they need to rerun the program with Python >= 2.6 and maybe provide some instructions on how to do so. However, to quote PEP 236:

The only lines that can appear before
a future_statement are:

  • The module docstring (if any).
  • Comments.
  • Blank lines.
  • Other future_statements.

So I can't do something like:

import __future__

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

Because it yields:

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

This snippet from the PEP seems to give hope of doing it inline:

Q: I want to wrap future_statements
in try/except blocks, so I can use
different code depending on which
version of Python I'm running. Why
can't I?

A: Sorry! try/except is a runtime
feature; future_statements are
primarily compile-time gimmicks, and
your try/except happens long after the
compiler is done. That is, by the
time you do try/except, the semantics
in effect for the module are already a
done deal. Since the try/except
wouldn't accomplish what it looks
like it should accomplish, it's simply
not allowed. We also want to keep
these special statements very easy to
find and to recognize.

Note that you can import __future__
directly, and use the information in
it, along with sys.version_info, to
figure out where the release you're
running under stands in relation to a
given feature's status.

Ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦纸 2024-07-17 13:38:06

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

这不是 README 文件的用途吗?

这是您的替代方案。 “包装器”:一小块 Python,在运行目标 aop 之前检查环境。

文件: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__ 的内容。 您仍然受到以下事实的束缚:from __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"

"I'd like to inform the user that they need to rerun the program with Python >= 2.6 and maybe provide some instructions on how to do so."

Isn't that what a README file is for?

Here's your alternative. A "wrapper": a little blob of Python that checks the environment before running your target aop.

File: 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()

What "direct import" means. You can examine the contents of __future__. You're still bound by the fact the a from __future__ import print_function is information to the compiler, but you can poke around before importing the module that does the real work.

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"
初与友歌 2024-07-17 13:38:06

我之前使用过的一个相当 hacky 但简单的方法是利用 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 特有的,但它快速且容易实现。

A rather hacky but simple method I've used before is to exploit the fact that byte literals were introduced in Python 2.6 and use something like this near the start of the file:

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

This is harmless in Python 2.6 or later, but a SyntaxError in any earlier versions. Anyone trying to compile your file will still get an error, but they also get whatever message you want to give.

You might think that as you will have to have this line after your from __future__ import print_function then it will be the import that generates the SyntaxError and you won't get to see the useful error message, but strangely enough the later error takes precedence. I suspect that as the error from the import isn't really a syntax error in itself it isn't raised on the first compilation pass, and so real syntax errors get raised first (but I'm guessing).

This might not meet you criteria for being 'graceful', and it is very Python 2.6 specific, but it is quick and easy to do.

兔小萌 2024-07-17 13:38:06

只需在与 “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

Just put a comment on the same line with the "from __future__ import ...", like this:

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

Since Python displays the line containing the error, if you try to run the module with Python 2.5 you'll get a nice, descriptive error:

    from __future__ import print_function, division  # We require Python 2.6 or later
SyntaxError: future feature print_function is not defined
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文