Add py::exec() as a shortcut for py::eval<py::eval_statements>()
diff --git a/docs/advanced/pycpp/utilities.rst b/docs/advanced/pycpp/utilities.rst
index 442d0e9..e3d9c6c 100644
--- a/docs/advanced/pycpp/utilities.rst
+++ b/docs/advanced/pycpp/utilities.rst
@@ -24,16 +24,10 @@
Evaluating Python expressions from strings and files
====================================================
-pybind11 provides the :func:`eval` and :func:`eval_file` functions to evaluate
+pybind11 provides the `eval`, `exec` and `eval_file` functions to evaluate
Python expressions and statements. The following example illustrates how they
can be used.
-Both functions accept a template parameter that describes how the argument
-should be interpreted. Possible choices include ``eval_expr`` (isolated
-expression), ``eval_single_statement`` (a single statement, return value is
-always ``none``), and ``eval_statements`` (sequence of statements, return value
-is always ``none``).
-
.. code-block:: cpp
// At beginning of file
@@ -48,7 +42,7 @@
int result = py::eval("my_variable + 10", scope).cast<int>();
// Evaluate a sequence of statements
- py::eval<py::eval_statements>(
+ py::exec(
"print('Hello')\n"
"print('world!');",
scope);
@@ -62,7 +56,7 @@
.. code-block:: cpp
- py::eval<py::eval_statements>(R"(
+ py::exec(R"(
x = get_answer()
if x == 42:
print('Hello World!')
@@ -70,3 +64,13 @@
print('Bye!')
)", scope
);
+
+.. note::
+
+ `eval` and `eval_file` accept a template parameter that describes how the
+ string/file should be interpreted. Possible choices include ``eval_expr``
+ (isolated expression), ``eval_single_statement`` (a single statement, return
+ value is always ``none``), and ``eval_statements`` (sequence of statements,
+ return value is always ``none``). `eval` defaults to ``eval_expr``,
+ `eval_file` defaults to ``eval_statements`` and `exec` is just a shortcut
+ for ``eval<eval_statements>``.
diff --git a/include/pybind11/eval.h b/include/pybind11/eval.h
index d4d26c1..c829b0c 100644
--- a/include/pybind11/eval.h
+++ b/include/pybind11/eval.h
@@ -62,6 +62,15 @@
return eval<mode>(expr, global, local);
}
+inline void exec(str expr, object global = object(), object local = object()) {
+ eval<eval_statements>(expr, global, local);
+}
+
+template <size_t N>
+void exec(const char (&s)[N], object global = object(), object local = object()) {
+ eval<eval_statements>(s, global, local);
+}
+
template <eval_mode mode = eval_statements>
object eval_file(str fname, object global = object(), object local = object()) {
if (!global) {
diff --git a/tests/test_eval.cpp b/tests/test_eval.cpp
index 9a8ac21..610d0e2 100644
--- a/tests/test_eval.cpp
+++ b/tests/test_eval.cpp
@@ -21,14 +21,14 @@
});
// Regular string literal
- py::eval<py::eval_statements>(
+ py::exec(
"message = 'Hello World!'\n"
"x = call_test()",
global, local
);
// Multi-line raw string literal
- auto result = py::eval<py::eval_statements>(R"(
+ py::exec(R"(
if x == 42:
print(message)
else:
@@ -37,7 +37,7 @@
);
auto x = local["x"].cast<int>();
- return result.is_none() && x == 42;
+ return x == 42;
});
m.def("test_eval", [global]() {