Python C API 中的 PyCompilerFlags 是什么?

What is PyCompilerFlags in Python C API?

如果您通过 C 调用检查了 Python C- API documentation 关于 运行 python 的代码,您总会发现提到 PyCompilerFlags,但除了文档的最后一部分,没有真正描述它是什么,也没有说明它的可能值及其对执行的影响。

PyCompilerFlags 是 C API 等效于传递给 compileflags 参数和 Python 中的相关函数。如果您在查看 CPython C-API 文档之前还不知道前后 Python 文档,那么这可能一点也不明显。

来自 compile:

The optional arguments flags and dont_inherit control which future statements affect the compilation of source. If neither is present (or both are zero) the code is compiled with those future statements that are in effect in the code that is calling compile(). If the flags argument is given and dont_inherit is not (or is zero) then the future statements specified by the flags argument are used in addition to those that would be used anyway. If dont_inherit is a non-zero integer then the flags argument is it – the future statements in effect around the call to compile are ignored.

Future statements are specified by bits which can be bitwise ORed together to specify multiple statements. The bitfield required to specify a given feature can be found as the compiler_flag attribute on the _Feature instance in the __future__ module.

在 link 到 future statements gives more details on how they work, and the link to the __future__ 之后有一张图表显示了可用的未来报表列表。


另一件可能不明显的事情:每个未来的功能标志对应于一个标志,该标志最终出现在 code 对象的 co_flags 属性中。所以:

code = compile('1 <> 2', '', 'eval', flags=__future__.barry_as_FLUFL.compiler_flag)
assert code.co_flags & CO_FUTURE_BARRY_AS_BDFL

在C中,如果你传递struct PyCompilerFlags flags = { CO_FUTURE_BARRY_AS_BDFL }得到同样的效果。

如果您想查看这些标志的实际数值,您必须查找相应的 CO_* constants in the C source or in the __future__ 来源。


C API 中的情况在某些方面略有不同。

  • 而不是同时传递 flagsdont_inherit,您只传递 flags,这是您希望在 PyRun_*PyCompile_* 调用期间生效的所有未来语句的完整集合。
  • 大多数函数采用 PyCompile_Flags 结构保存一个 int,而不是原始 int。这只是为了类型检查的目的;在内存中,保存 int 的结构与 int 的存储方式相同。
  • 许多函数通过指针获取它们的标志,因此您可以在 运行 代码后检索可能更新的标志集。

让我们看一个完整的例子。我将使用 Python 2.7,即使我一直在 linking 到 3.7 文档,只是因为使用 print 的示例比使用前向注释的示例更简单。

此代码打印一个空元组:

print()

但是如果你 运行 第一个 PyRun_SimpleStringFlags,传递 CO_FUTURE_PRINT_FUNCTION (0x10000) 作为 标志 `,它将打印一个空行,la Python 3.

如果您运行此代码:

from __future__ import print_function
print()

…那么无论你传入0还是CO_FUTURE_PRINT_FUNCTION,都会打印一个空行。在调用之后,如果您查看通过引用传入的 flags,它将包含 CO_FUTURE_PRINT_FUNCTION or'd。因此,如果您一次编译和 运行 一个块,您可以将相同的值传递给下一个字符串,它将继承该 future 标志。 (很像当你在交互式解释器中写一个 future 语句时,它会影响你之后解释的所有语句。)