使用 pybind11 或 Python C API 编译并执行 AST

Compile and execute AST using pybind11 or Python C API

我想使用 Pybind11 或直接 Python C API:

将这段 Python 代码翻译成 C++ 代码
import ast

code = "print('Hello World!')"

code_ast = ast.parse(code, mode="exec") # "code" being a string containing code
# ... perform some modifications on "code_ast"
exec(compile(code_ast, filename="<ast>", mode="exec"))

这是我目前使用的 Pybind11:

#include <iostream>
#include "pybind11/embed.h"

namespace py = pybind11;

std::string code = "print('Hello World!')";

py::module ast = py::module::import("ast");
py::module builtins = py::module::import("builtins");

py::object code_ast = ast.attr("parse")(code, "<unknown>", "exec");
// ... perform some modifications on "code_ast"
py::object compiled_code = builtins.attr("compile")(code_ast, "<ast>", "exec");
builtins.attr("exec")(compiled_code);

不幸的是,最后一行 C++ 代码引发了运行时错误:SystemError: frame does not exist.

我不确定我是否理解这个错误,我尝试将 globalslocals 传递给 exec,但没有解决问题。

编辑:通过globals时,它表示:SystemError: <built-in function globals> returned NULL without setting an error

关于如何正确实现这一目标的任何想法?

我找到了答案,我没有使用 Pybind11 中的 globals 函数,而是 Python (builtins.attr("globals")()) 中的内置函数。

这是工作版本:

py::module ast = py::module::import("ast");
py::module builtins = py::module::import("builtins");

py::object code_ast = ast.attr("parse")(code, "<unknown>", "exec");
// ... perform some modifications on "code_ast"
py::object compiled_code = builtins.attr("compile")(code_ast, "<ast>", "exec");
builtins.attr("exec")(compiled_code, py::globals());