我有一个需要支持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"]
这些都不起作用。是否有可能使这项工作?
答案 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语句很有用。