首页 > 解决方案 > Python C API 中的 PyCompilerFlags 是什么?

问题描述

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

标签: pythoncpython

解决方案


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

来自compile

可选参数flagsdont_inherit控制哪些未来语句会影响源代码的编译。如果两者都不存在(或两者都为零),则使用那些在调用的代码中有效的未来语句编译代码compile()。如果给出了flags参数并且dont_inherit不是(或为零),那么除了将使用的那些语句之外,还会使用由flags参数指定的未来语句。如果dont_inherit是一个非零整数,那么flags参数就是它——在调用 compile 时生效的未来语句将被忽略。

未来的语句由位指定,这些位可以按位或一起指定多个语句。指定给定特征所需的位域可以作为模块中实例的compiler_flag属性找到。_Feature__future__

指向未来报表的链接提供了有关它们如何工作的更多详细信息,并且指向该链接的链接__future__有一个图表,显示了可用的未来报表列表。


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

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_*在 C 源代码或源代码中查找相应的常量__future__


C API 在某些方面略有不同。

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

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

此代码打印一个空元组:

print()

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

如果您运行此代码:

from __future__ import print_function
print()

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


推荐阅读