如何从C扩展模块

时间:2015-10-23 21:53:38

标签: python python-c-api python-c-extension

我有一个需要支持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是表示列表PyObject

["print_function"]

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

1 个答案:

答案 0 :(得分:3)

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

您可以使用将来的语句或使用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语句很有用。