Skip to content

Commit 0d3fc35

Browse files
committed
complete rewrite of eval/exec patch
1 parent c6ad2c4 commit 0d3fc35

File tree

6 files changed

+178
-282
lines changed

6 files changed

+178
-282
lines changed

docs/advanced.rst

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ helper class that is defined as follows:
282282
283283
The macro :func:`PYBIND11_OVERLOAD_PURE` should be used for pure virtual
284284
functions, and :func:`PYBIND11_OVERLOAD` should be used for functions which have
285-
a default implementation.
285+
a default implementation.
286286

287287
There are also two alternate macros :func:`PYBIND11_OVERLOAD_PURE_NAME` and
288288
:func:`PYBIND11_OVERLOAD_NAME` which take a string-valued name argument
@@ -1612,32 +1612,38 @@ work, it is important that all lines are indented consistently, i.e.:
16121612
.. [#f4] http://www.sphinx-doc.org
16131613
.. [#f5] http://github.com/pybind/python_example
16141614
1615-
Calling Python from C++
1616-
=======================
1615+
Evaluating Python expressions from strings and files
1616+
====================================================
16171617

1618-
Pybind11 also allows to call python code from C++. Note that this code assumes, that the intepreter is already initialized.
1618+
pybind11 provides the :func:`eval` and :func:`eval_file` functions to evaluate
1619+
Python expressions and statements. The following example illustrates how they
1620+
can be used.
1621+
1622+
Both functions accept a template parameter that describes how the argument
1623+
should be interpreted. Possible choices include ``eval_expr`` (isolated
1624+
expression), ``eval_single_statement`` (a single statement, return value is
1625+
always ``none``), and ``eval_statements`` (sequence of statements, return value
1626+
is always ``none``).
16191627

16201628
.. code-block:: cpp
16211629
1622-
// get the main module, so we can access and declare stuff
1623-
py::module main_module = py::module::import("__main__");
1624-
1625-
//get the main namespace, so I can declare variables
1626-
py::object main_namespace = main_module.attr("__dict__");
1630+
// At beginning of file
1631+
#include <pybind11/eval.h>
1632+
1633+
...
1634+
1635+
// Evaluate in scope of main module
1636+
py::object scope = py::module::import("__main__").attr("__dict__");
1637+
1638+
// Evaluate an isolated expression
1639+
int result = py::eval("my_variable + 10", scope).cast<int>();
16271640
1628-
//now execute code
1629-
py::exec(
1630-
"print('Hello World1!')\n"
1631-
"print('Other Data');",
1632-
main_namespace);
1641+
// Evaluate a sequence of statements
1642+
py::eval<py::eval_statements>(
1643+
"print('Hello')\n"
1644+
"print('world!');",
1645+
scope);
16331646
1634-
//execute a single statement
1635-
py::exec_statement("x=42", main_namespace);
1647+
// Evaluate the statements in an separate Python file on disk
1648+
py::eval_file("script.py", scope);
16361649
1637-
//ok, now I want to get the result of a statement, we'll use x in this example
1638-
py::object res = py::eval("x");
1639-
std:cout << "Yielded: " << res.cast<int>() << std::endl;
1640-
1641-
//or we can execute a file within the same content
1642-
py::exec_file("my_script.py", main_namespace);
1643-

docs/reference.rst

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -244,26 +244,4 @@ Passing extra arguments to the def function
244244
.. function:: name::name(const char *value)
245245

246246
Used to specify the function name
247-
248-
Calling Python from C++
249-
=======================
250-
251-
.. function:: eval(str string, object global = object(), object local = object())
252-
253-
Evaluate a statement, i.e. one that does not yield None.
254-
The return value the result of the expression. It throws pybind11::error_already_set if the commands are invalid.
255-
256-
.. function:: exec(str string, object global = object(), object local = object())
257-
258-
Execute a set of statements. The return value the result of the code. It throws pybind11::error_already_set if the commands are invalid.
259-
260-
.. function:: exec_statement(str string, object global = object(), object local = object())
261-
262-
Execute a single statement. The return value the result of the code. It throws pybind11::error_already_set if the commands are invalid.
263-
264-
.. function:: exec_file(str filename, object global = object(), object local = object())
265-
266-
Execute a file. The function exec_file will throw std::invalid_argument if the file cannot be opened.
267-
The return value the result of the code. It throws pybind11::error_already_set if the commands are invalid and
268-
std::invalid_argument if the file cannot be opened.
269247

example/example18.cpp

Lines changed: 52 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
example/example18.cpp -- Usage of exec, eval etc.
2+
example/example18.cpp -- Usage of eval() and eval_file()
33
44
Copyright (c) 2016 Klemens D. Morgenstern
55
@@ -8,113 +8,95 @@
88
*/
99

1010

11-
#include <pybind11/exec.h>
11+
#include <pybind11/eval.h>
1212
#include "example.h"
1313

1414
void example18() {
1515
py::module main_module = py::module::import("__main__");
1616
py::object main_namespace = main_module.attr("__dict__");
1717

18-
bool executed = false;
18+
bool ok = false;
1919

20-
main_module.def("call_test", [&]()-> int {executed = true; return 42;});
20+
main_module.def("call_test", [&]() -> int {
21+
ok = true;
22+
return 42;
23+
});
2124

22-
cout << "exec test" << endl;
25+
cout << "eval_statements test" << endl;
2326

24-
py::exec(
27+
auto result = py::eval<py::eval_statements>(
2528
"print('Hello World!');\n"
26-
"x = call_test();",
27-
main_namespace);
29+
"x = call_test();", main_namespace);
2830

29-
if (executed)
30-
cout << "exec passed" << endl;
31-
else {
32-
cout << "exec failed" << endl;
33-
}
31+
if (ok && result == py::none())
32+
cout << "eval_statements passed" << endl;
33+
else
34+
cout << "eval_statements failed" << endl;
3435

3536
cout << "eval test" << endl;
3637

3738
py::object val = py::eval("x", main_namespace);
3839

3940
if (val.cast<int>() == 42)
4041
cout << "eval passed" << endl;
41-
else {
42+
else
4243
cout << "eval failed" << endl;
43-
}
44-
4544

46-
executed = false;
47-
cout << "exec_statement test" << endl;
45+
ok = false;
46+
cout << "eval_single_statement test" << endl;
4847

49-
py::exec_statement("y = call_test();", main_namespace);
48+
py::eval<py::eval_single_statement>(
49+
"y = call_test();", main_namespace);
5050

51+
if (ok)
52+
cout << "eval_single_statement passed" << endl;
53+
else
54+
cout << "eval_single_statement failed" << endl;
5155

52-
if (executed)
53-
cout << "exec_statement passed" << endl;
54-
else {
55-
cout << "exec_statement failed" << endl;
56-
}
57-
58-
cout << "exec_file test" << endl;
56+
cout << "eval_file test" << endl;
5957

6058
int val_out;
6159
main_module.def("call_test2", [&](int value) {val_out = value;});
6260

63-
64-
py::exec_file("example18_call.py", main_namespace);
65-
66-
if (val_out == 42)
67-
cout << "exec_file passed" << endl;
68-
else {
69-
cout << "exec_file failed" << endl;
70-
}
71-
72-
executed = false;
73-
cout << "exec failure test" << endl;
7461
try {
75-
py::exec("non-sense code ...");
76-
}
77-
catch (py::error_already_set & err) {
78-
executed = true;
79-
}
80-
if (executed)
81-
cout << "exec failure test passed" << endl;
82-
else {
83-
cout << "exec failure test failed" << endl;
62+
result = py::eval_file("example18_call.py", main_namespace);
63+
} catch (...) {
64+
result = py::eval_file("example/example18_call.py", main_namespace);
8465
}
8566

67+
if (val_out == 42 && result == py::none())
68+
cout << "eval_file passed" << endl;
69+
else
70+
cout << "eval_file failed" << endl;
8671

87-
executed = false;
88-
cout << "exec_file failure test" << endl;
89-
try {
90-
py::exec_file("none-existing file");
91-
}
92-
catch (std::invalid_argument & err) {
93-
executed = true;
94-
}
95-
if (executed)
96-
cout << "exec_file failure test passed" << endl;
97-
else {
98-
cout << "exec_file failure test failed" << endl;
99-
}
100-
101-
executed = false;
72+
ok = false;
10273
cout << "eval failure test" << endl;
10374
try {
104-
py::eval("print('dummy')");
105-
}
106-
catch (py::error_already_set & err) {
107-
executed = true;
75+
py::eval("nonsense code ...");
76+
} catch (py::error_already_set &) {
77+
PyErr_Clear();
78+
ok = true;
10879
}
109-
if (executed)
80+
81+
if (ok)
11082
cout << "eval failure test passed" << endl;
111-
else {
83+
else
11284
cout << "eval failure test failed" << endl;
85+
86+
ok = false;
87+
cout << "eval_file failure test" << endl;
88+
try {
89+
py::eval_file("nonexisting file");
90+
} catch (std::exception &) {
91+
ok = true;
11392
}
93+
94+
if (ok)
95+
cout << "eval_file failure test passed" << endl;
96+
else
97+
cout << "eval_file failure test failed" << endl;
11498
}
11599

116100
void init_ex18(py::module & m) {
117-
m.def("example18", &example18);
101+
m.def("example18", &example18);
118102
}
119-
120-

example/example18.ref

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
exec test
2-
Hello World!
3-
exec passed
1+
eval_statements test
2+
eval_statements passed
43
eval test
54
eval passed
6-
exec_statement test
7-
exec_statement passed
8-
exec_file test
9-
exec_file passed
10-
exec failure test
11-
exec failure test passed
12-
exec_file failure test
13-
exec_file failure test passed
5+
eval_single_statement test
6+
eval_single_statement passed
7+
eval_file test
8+
eval_file passed
149
eval failure test
1510
eval failure test passed
11+
eval_file failure test
12+
eval_file failure test passed
13+
Hello World!

include/pybind11/eval.h

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
pybind11/exec.h: Support for evaluating Python expressions and statements
3+
from strings and files
4+
5+
Copyright (c) 2016 Klemens Morgenstern <klemens.morgenstern@ed-chemnitz.de> and
6+
Wenzel Jakob <wenzel.jakob@epfl.ch>
7+
8+
All rights reserved. Use of this source code is governed by a
9+
BSD-style license that can be found in the LICENSE file.
10+
*/
11+
12+
#pragma once
13+
14+
#pragma once
15+
16+
#include "pytypes.h"
17+
18+
NAMESPACE_BEGIN(pybind11)
19+
20+
enum eval_mode {
21+
/// Evaluate a string containing an isolated expression
22+
eval_expr,
23+
24+
/// Evaluate a string containing a single statement. Returns \c none
25+
eval_single_statement,
26+
27+
/// Evaluate a string containing a sequence of statement. Returns \c none
28+
eval_statements
29+
};
30+
31+
template <eval_mode mode = eval_expr>
32+
object eval(const std::string& str, object global = object(), object local = object()) {
33+
if (!global) {
34+
global = object(PyEval_GetGlobals(), true);
35+
if (!global)
36+
global = dict();
37+
}
38+
if (!local)
39+
local = global;
40+
41+
int start;
42+
switch (mode) {
43+
case eval_expr: start = Py_eval_input; break;
44+
case eval_single_statement: start = Py_single_input; break;
45+
case eval_statements: start = Py_file_input; break;
46+
default: pybind11_fail("invalid evaluation mode");
47+
}
48+
49+
object result(PyRun_String(str.c_str(), start, global.ptr(), local.ptr()), false);
50+
51+
if (!result)
52+
throw error_already_set();
53+
return result;
54+
}
55+
56+
template <eval_mode mode = eval_statements>
57+
object eval_file(const std::string& fname, object global = object(), object local = object()) {
58+
if (!global) {
59+
global = object(PyEval_GetGlobals(), true);
60+
if (!global)
61+
global = dict();
62+
}
63+
if (!local)
64+
local = global;
65+
66+
int start;
67+
switch (mode) {
68+
case eval_expr: start = Py_eval_input; break;
69+
case eval_single_statement: start = Py_single_input; break;
70+
case eval_statements: start = Py_file_input; break;
71+
default: pybind11_fail("invalid evaluation mode");
72+
}
73+
74+
FILE *f = fopen(fname.c_str(), "r");
75+
if (!f)
76+
pybind11_fail("File \"" + fname + "\" could not be opened!");
77+
78+
object result(PyRun_FileEx(f, fname.c_str(), Py_file_input, global.ptr(),
79+
local.ptr(), 1),
80+
false);
81+
82+
if (!result)
83+
throw error_already_set();
84+
85+
return result;
86+
}
87+
88+
NAMESPACE_END(pybind11)

0 commit comments

Comments
 (0)