Python 如何从C扩展模块中的_future__导入

Python 如何从C扩展模块中的_future__导入,python,python-c-api,python-c-extension,Python,Python C Api,Python C Extension,我有一个扩展模块,需要支持Python 2和Python 3。当它加载时,我想从_future _导入打印_函数执行类似的操作,以便如果有人尝试执行此操作: PyRun_SimpleString("print 'foo'"); 它将失败,但如果他们这样做: PyRun_SimpleString("print('foo', file=sys.stdout)"); 它会成功的。我已经尝试了很多方法,包括from future语句的PyRun\u SimpleString。像这样: PyRun_S

我有一个扩展模块,需要支持Python 2和Python 3。当它加载时,我想从_future _导入打印_函数执行类似的操作,以便如果有人尝试执行此操作:

PyRun_SimpleString("print 'foo'");
它将失败,但如果他们这样做:

PyRun_SimpleString("print('foo', file=sys.stdout)");
它会成功的。我已经尝试了很多方法,包括from future语句的
PyRun\u SimpleString
。像这样:

PyRun_SimpleString("from __future__ import print_function");
PyImport_ImportModuleEx("__future__", nullptr, nullptr, fromlist);
我还试着像这样调用
PyImport\u importmodulex

PyRun_SimpleString("from __future__ import print_function");
PyImport_ImportModuleEx("__future__", nullptr, nullptr, fromlist);
其中
fromlist
是一个
PyObject
表示列表
[“打印功能”]


这两种方法都不管用。有可能做到这一点吗?

PyRun\u SimpleString没有任何地方可以指定编译器标志,但是有一个具有更多选项的选项。例如,
PyRun\u SimpleStringFlags
执行
PyRun\u SimpleString
所执行的操作,但使用
flags
参数指定编译器标志
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu SimpleStringFlags执行的语句可以修改
标志
,并且使用相同的
标志的其他调用将看到更改

您可以使用将来的语句或C级标志定义初始化标志。大多数可能的标志没有在C-api文档中列出(因为C-api文档有点糟糕),但是您可以在
\uuuuu future\uuuuu
模块或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\uuuuuuu future\uuuuuu import print\u函数
的作用下运行字符串

PyCompilerFlags flags = {CO_FUTURE_PRINT_FUNCTION};
PyRun_SimpleStringFlags(command, &flags);
如果您想保存用户执行的未来语句的效果,您应该将PyCompilerFlags结构保存在某个位置,并对所有调用使用相同的结构



尽管如此,我不认为自动应用来自未来导入打印功能的
是正确的做法。这会让人们感到惊讶,因为他们期待的是他们使用的任何解释器的默认行为。另外,
PyRun\u InteractiveOneFlags
可能有助于用户输入多行Python语句。

为什么扩展模块使用
PyRun\u SimpleString
,尤其是打印东西?这并不完全是为了说明问题。但是,它确实公开了一个嵌入式解释器。i、 您可以在程序中执行一些操作,以跳转到python提示符,也可以运行一些命令来执行python代码并显示解释器的输出(这些命令是通过
PyRun\u SimpleString
传递的。我需要的是一种禁用打印语句的方法,这样,如果有人运行打印语句,他们就会出现错误。这与您所问的问题完全不同,解决方案也完全不同。嗯,好吗?我不确定我是否遵循了。命令用户是输入get pass to
PyRun\u SimpleString
。因此,请确保
PyRun\u SimpleString(“打印'foo'))
生成错误,我还确保在他们输入该命令时会生成错误。这正是我试图解决的问题。如果您的语句不那么模棱两可,这可能有助于我理解您的意思。您提出的问题是关于在调用中获得未来语句的效果
PyRun_SimpleString
,而您实际试图解决的问题是在未来语句的影响下运行用户提供的Python代码。
PyRun_SimpleString
不是该工作的工具。谢谢,这很有帮助。有什么方法可以获得解释器当前所受影响的标志集吗?我这样做uld获取该组标志,并添加
CO_FUTURE_PRINT_函数
。这是在一个扩展模块中,该模块必须使用单个代码库支持Py2和Py3,尤其是一组测试。因此,强制执行PRINT函数是最好的方法(据我所知)为了确保测试套件始终通过。@ZacharyTurner:我认为解释器不会暴露这一点。不过,我确实找到了如何将标志从一条语句保存到下一条语句的方法。至于测试套件,如果保留用户执行的未来语句,您只需将
from\uuuuuuuuuuuuuuuuuuuuuu未来导入打印功能
在测试设置中。