【问题标题】:How can we make __future__ imports global?我们怎样才能使 __future__ 进口全球化?
【发布时间】:2012-11-26 06:24:59
【问题描述】:

规格:Python 2.7

我正在开发一个包含多个模块的项目,我想在所有模块中激活 __future__ 模块中的一些功能。我想在一个模块上导入我需要的所有功能,然后将该单个模块导入到其他模块中,并让这些功能在所有模块中都处于活动状态,或者类似的效果。

我试过了:

[A.py]

from __future__ import division

[B.py]

import A
print(1/2)

运行 B.py,除法仍然是整数。我试过了:

[A.py]

print(1/2)

[B.py]

from __future__ import division
import A

运行 B.py 给出了相同的结果。对于前面的两个示例,我还尝试通过“from A import *”切换“import A”,结果相同。

我在 Google 上搜索了一段时间,并在 Python 文档中找到了关于 __future__ 模块如何工作的最佳描述,很明显。在那里,我只能确保这些功能在它们导入的模块中处于活动状态,而没有提及如何在全局范围内执行此操作。

所以我想知道是否有办法做到这一点,无论是我描述的方式,还是创建某种运行时配置文件,或通过其他方式。

【问题讨论】:

    标签: python python-2.7


    【解决方案1】:

    没有办法用语言做到这一点;从这个意义上说,你真的不能让__future__ 导入全局。 (好吧,您可能可以用imp 或其他一些复杂的东西替换普通的import 语句。请参阅Future statement 文档并向下滚动到“代码编译者……”但是这样的任何事情几乎肯定是个坏主意。 )

    原因是from __future__ import division 并不是真正的正常导入。或者,更确切地说,它不仅仅是一个正常的导入。实际上,您确实获得了一个名为division 的名称,您可以对其进行检查,但仅仅拥有该值没有任何影响——因此将其传递给其他模块不会影响这些模块。除了正常的导入之外,Python 还具有特殊的魔力,可以检测模块顶部或交互式解释器中的 __future__ 导入,并更改代码的编译方式。如果您想了解所有详细信息,请参阅 future 了解“真正的导入”部分,以及 Future statements 了解“魔术”部分。

    并且没有配置文件可以让您执行此操作。但是有一个命令行参数:

    python -Qnew main.py
    

    这与在任何地方执行from __future__ import division 的效果相同。

    您可以将其添加到#! 行,或者在您的shell 中添加alias pyfuturediv='python -Qnew'(甚至alias python='python -Qnew'),或者其他任何内容,这可能与您的目的的配置文件一样好。

    但实际上,如果您想确保模块 B 获得新式划分,您可能应该首先在 B 中声明 __future__

    或者,当然,您可以只为 Python 3.0+ 而不是 2.3-2.7 编写代码。 (请注意,一些核心开发人员反对使用命令行参数,因为“全局获取特性 X 的正确方法是使用 Python >= 特性 X 的 MandatoryRelease 的版本”。)或者当你的意思是 @ 时使用 // 987654339@.

    另一种可能性是使用six,该模块旨在让您编写几乎是 Python 3.3 的代码,并使其在 2.4-2.7(和 3.0-3.2)中正常工作。例如,你没有得到print 函数,但你得到了一个完全相同的print_ 函数。你没有得到 Unicode 文字,但你得到了 u() 假文字——再加上源代码中的 UTF-8 编码声明,几乎就足够了。它还提供了很多你无法从 __future__ 获得的东西——StringIOBytesIOexec 作为函数、next 函数等。

    如果问题是您有 1000 个源文件,并且很难全部编辑它们,您可以使用 sed,或者使用 3to2 并仅使用修复除法的选项,或者……

    【讨论】:

    • +1 -- 关键是from __future__ import [foo] 根本不是导入语句;这是一个future statement,在编译时有效果。
    • @senderle:好点;我会重写一些东西以使其更清楚。虽然它实际上一个导入语句,但它不是只是一个导入语句。文档准确定义了 foo 将被该语句绑定的内容。
    • 我不控制要发布应用程序的系统,因此 Python 3.x 不在讨论范围内。我不打算只包括除法,这只是一个例子,我计划包括与 2.7 相关的所有四个。我没有大量文件要更改,我可以手动完成。我只是想让它在未来的版本中更不容易出错,而且更漂亮。 ^_^ 我不想继续将这些行添加到我碰巧创建的每个模块中,并且预计会创建其他几个。如果它涵盖所有功能,我可能会使用命令行选项。
    • @xor:有divisionprint_functionunicode_literals……第四个是什么?无论如何,真的,如果你想编写 Python 3 代码但让它在 2.7 中运行,可能有更好的方法来做到这一点,比如运行3to2(甚至在你的setup.py 中自动运行),或者使用six 库.或者放入显式的__future__ 语句——说真的,后来的维护者(或者一年后的你)会被例如 2.7 代码中的打印函数弄糊涂,除非有某种明确的指示表明发生了什么——这是__future__ 导入丑陋且必须位于顶部的部分原因。
    • absolute_import 在 Python 2 中未启用(它会破坏向后兼容性)例如,如果你的包中有 os.py 文件,那么包内的 import os 如果你运行一个同一目录中的脚本(使用顶级脚本修复它)。
    【解决方案2】:

    另一种方法是使用isortisort 有一个 -a 命令行标志,用于向您指定的文件添加导入。只需在不带参数的情况下运行 isort 即可在当前工作目录和所有子目录中的所有 python 文件上递归运行它。

    如果像我一样,您在该文件夹中有一个虚拟环境,并且正在使用 git(或有仅列出您的文件的等效方式)并且不想在该虚拟环境中的所有文件上运行它,您可以使用类似的东西:

    git ls-tree -r HEAD --name-only | grep "\.py$" | xargs isort -a -y "from __future__ import division"

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-02
      • 1970-01-01
      • 2016-09-14
      • 2015-03-15
      • 1970-01-01
      • 2022-01-11
      • 2020-09-24
      相关资源
      最近更新 更多