Python C API 中的 PyCompilerFlags 是什么?

Sha*_*tef 5 python cpython

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

aba*_*ert 4

PyCompilerFlagsC API 相当于传递给Python 中相关函数的flags参数。compile如果您在查看 CPython C-API 文档之前尚不了解 Python 文档,那么这可能一点也不明显。

\n

compile

\n
\n

可选参数flagsdont_inherit控制哪些未来语句会影响源代码的编译。如果两者都不存在(或两者都为零),则使用在调用的代码中有效的未来语句来编译代码compile()。如果给出了flags参数,而dont_inherit未给出(或为零),则除了那些无论如何都会使用的语句之外,还会使用由flags参数指定的 future 语句。如果dont_inherit是非零整数,则标志参数是 \xe2\x80\x93 ,围绕编译调用的未来语句将被忽略。

\n

未来语句由位指定,这些位可以按位或运算在一起以指定多个语句。指定给定功能所需的位字段可以作为模块中实例的compiler_flag属性找到。_Feature__future__

\n
\n

未来报表的链接提供了有关其工作原理的更多详细信息,并且链接有__future__一个图表,显示可用的未来报表列表。

\n
\n

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

\n
code = compile(\'1 <> 2\', \'\', \'eval\', flags=__future__.barry_as_FLUFL.compiler_flag)\nassert code.co_flags & CO_FUTURE_BARRY_AS_BDFL\n
Run Code Online (Sandbox Code Playgroud)\n

在C中,如果通过struct PyCompilerFlags flags = { CO_FUTURE_BARRY_AS_BDFL }可以得到同样的效果。

\n

CO_*如果您想查看这些标志的实际数值,则必须在 C 源代码或源代码中查找相应的常量__future__

\n
\n

C API 中的情况在几个方面略有不同。

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

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

\n

此代码打印一个空元组:

\n
print()\n
Run Code Online (Sandbox Code Playgroud)\n

但是如果你使用 运行第一个PyRun_SimpleStringFlags,并传递CO_FUTURE_PRINT_FUNCTION(0x10000) 作为标志`,它将打印一个空行,就像 Python 3 那样。

\n

如果您运行此代码:

\n
from __future__ import print_function\nprint()\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x80\xa6 那么无论你传入0CO_FUTURE_PRINT_FUNCTION,它都会打印一个空行。在调用之后,如果您查看通过引用传入的标志CO_FUTURE_PRINT_FUNCTION,它将具有“或”。因此,如果您一次编译并运行一个块,则可以将相同的值传递给下一个字符串,并且它将继承该 future 标志。(就像当您在交互式解释器中编写未来语句时,它会影响您之后解释的所有语句。)

\n