如何在 C 扩展模块中从 __future__ 导入

How to import from __future__ in C extension module

我有一个扩展模块需要支持 Python 2 和 Python 3。当它加载时,我想做类似 from __future__ import print_function 的事情,这样如果有人尝试为此:

PyRun_SimpleString("print 'foo'");

它会失败,但如果他们这样做:

PyRun_SimpleString("print('foo', file=sys.stdout)");

一定会成功的。我已经尝试了很多事情,包括来自未来声明的 PyRun_SimpleString 。像这样:

PyRun_SimpleString("from __future__ import print_function");

我也试过这样调用 PyImport_ImportModuleEx

PyImport_ImportModuleEx("__future__", nullptr, nullptr, fromlist);

其中 fromlist 是表示列表 ["print_function"]

PyObject

这些都不起作用。有可能使这项工作吗?

PyRun_SimpleString 没有任何地方可以指定编译器标志,但是 whole host of related functions 有更多可用选项。例如,PyRun_SimpleStringFlagsPyRun_SimpleString 做的事情,但使用 flags 参数来指定编译器标志。使用 PyRun_SimpleStringFlags 执行的 __future__ 语句可以修改 flags,并且使用相同 flags.

的其他调用将看到更改

您可以使用 future 语句或 C 级标志定义来初始化 flags。大多数可能的标志都没有在 C-api 文档中列出(因为 C-api 文档有点烂),但您可以在 __future__ 模块或Python 源代码的几个部分。

>>> import __future__
>>> for name in dir(__future__):
...     if name.startswith('CO_'):
...         print name
...
CO_FUTURE_ABSOLUTE_IMPORT
CO_FUTURE_DIVISION
CO_FUTURE_PRINT_FUNCTION
CO_FUTURE_UNICODE_LITERALS
CO_FUTURE_WITH_STATEMENT
CO_GENERATOR_ALLOWED
CO_NESTED

例如,您可以 运行 一个受 from __future__ import print_function

影响的字符串
PyCompilerFlags flags = {CO_FUTURE_PRINT_FUNCTION};
PyRun_SimpleStringFlags(command, &flags);

如果您想保存用户执行的未来语句的效果,您可以将 PyCompilerFlags 结构保存在某处,并对所有调用使用相同的结构。


话虽如此,我认为自动应用 from __future__ import print_function 并不是正确的做法。人们会惊讶地期待他们所使用的任何解释器的默认行为。此外,PyRun_InteractiveOneFlags 可能有助于让用户输入多行 Python 语句。