Dean Moldovan | 67b52d8 | 2016-10-16 19:12:43 +0200 | [diff] [blame] | 1 | Utilities |
| 2 | ######### |
| 3 | |
| 4 | Using Python's print function in C++ |
| 5 | ==================================== |
| 6 | |
| 7 | The usual way to write output in C++ is using ``std::cout`` while in Python one |
| 8 | would use ``print``. Since these methods use different buffers, mixing them can |
| 9 | lead to output order issues. To resolve this, pybind11 modules can use the |
| 10 | :func:`py::print` function which writes to Python's ``sys.stdout`` for consistency. |
| 11 | |
| 12 | Python's ``print`` function is replicated in the C++ API including optional |
| 13 | keyword arguments ``sep``, ``end``, ``file``, ``flush``. Everything works as |
| 14 | expected in Python: |
| 15 | |
| 16 | .. code-block:: cpp |
| 17 | |
| 18 | py::print(1, 2.0, "three"); // 1 2.0 three |
| 19 | py::print(1, 2.0, "three", "sep"_a="-"); // 1-2.0-three |
| 20 | |
| 21 | auto args = py::make_tuple("unpacked", true); |
| 22 | py::print("->", *args, "end"_a="<-"); // -> unpacked True <- |
| 23 | |
Henry Schreiner | 8b40505 | 2017-08-24 17:12:43 -0700 | [diff] [blame] | 24 | .. _ostream_redirect: |
| 25 | |
| 26 | Capturing standard output from ostream |
| 27 | ====================================== |
| 28 | |
| 29 | Often, a library will use the streams ``std::cout`` and ``std::cerr`` to print, |
| 30 | but this does not play well with Python's standard ``sys.stdout`` and ``sys.stderr`` |
| 31 | redirection. Replacing a library's printing with `py::print <print>` may not |
| 32 | be feasible. This can be fixed using a guard around the library function that |
| 33 | redirects output to the corresponding Python streams: |
| 34 | |
| 35 | .. code-block:: cpp |
| 36 | |
| 37 | #include <pybind11/iostream.h> |
| 38 | |
| 39 | ... |
| 40 | |
| 41 | // Add a scoped redirect for your noisy code |
| 42 | m.def("noisy_func", []() { |
| 43 | py::scoped_ostream_redirect stream( |
| 44 | std::cout, // std::ostream& |
Henry Schreiner | 6bcd220 | 2020-10-03 13:38:03 -0400 | [diff] [blame] | 45 | py::module_::import("sys").attr("stdout") // Python output |
Henry Schreiner | 8b40505 | 2017-08-24 17:12:43 -0700 | [diff] [blame] | 46 | ); |
| 47 | call_noisy_func(); |
| 48 | }); |
| 49 | |
| 50 | This method respects flushes on the output streams and will flush if needed |
| 51 | when the scoped guard is destroyed. This allows the output to be redirected in |
| 52 | real time, such as to a Jupyter notebook. The two arguments, the C++ stream and |
| 53 | the Python output, are optional, and default to standard output if not given. An |
| 54 | extra type, `py::scoped_estream_redirect <scoped_estream_redirect>`, is identical |
| 55 | except for defaulting to ``std::cerr`` and ``sys.stderr``; this can be useful with |
| 56 | `py::call_guard`, which allows multiple items, but uses the default constructor: |
| 57 | |
| 58 | .. code-block:: py |
| 59 | |
| 60 | // Alternative: Call single function using call guard |
| 61 | m.def("noisy_func", &call_noisy_function, |
| 62 | py::call_guard<py::scoped_ostream_redirect, |
| 63 | py::scoped_estream_redirect>()); |
| 64 | |
| 65 | The redirection can also be done in Python with the addition of a context |
| 66 | manager, using the `py::add_ostream_redirect() <add_ostream_redirect>` function: |
| 67 | |
| 68 | .. code-block:: cpp |
| 69 | |
| 70 | py::add_ostream_redirect(m, "ostream_redirect"); |
| 71 | |
| 72 | The name in Python defaults to ``ostream_redirect`` if no name is passed. This |
| 73 | creates the following context manager in Python: |
| 74 | |
| 75 | .. code-block:: python |
| 76 | |
| 77 | with ostream_redirect(stdout=True, stderr=True): |
| 78 | noisy_function() |
| 79 | |
| 80 | It defaults to redirecting both streams, though you can use the keyword |
| 81 | arguments to disable one of the streams if needed. |
| 82 | |
| 83 | .. note:: |
| 84 | |
| 85 | The above methods will not redirect C-level output to file descriptors, such |
| 86 | as ``fprintf``. For those cases, you'll need to redirect the file |
| 87 | descriptors either directly in C or with Python's ``os.dup2`` function |
| 88 | in an operating-system dependent way. |
| 89 | |
Dean Moldovan | 6d2411f | 2017-04-22 23:24:13 +0200 | [diff] [blame] | 90 | .. _eval: |
| 91 | |
Dean Moldovan | 67b52d8 | 2016-10-16 19:12:43 +0200 | [diff] [blame] | 92 | Evaluating Python expressions from strings and files |
| 93 | ==================================================== |
| 94 | |
Dean Moldovan | 076c738 | 2017-04-30 01:53:06 +0200 | [diff] [blame] | 95 | pybind11 provides the `eval`, `exec` and `eval_file` functions to evaluate |
Dean Moldovan | 67b52d8 | 2016-10-16 19:12:43 +0200 | [diff] [blame] | 96 | Python expressions and statements. The following example illustrates how they |
| 97 | can be used. |
| 98 | |
Dean Moldovan | 67b52d8 | 2016-10-16 19:12:43 +0200 | [diff] [blame] | 99 | .. code-block:: cpp |
| 100 | |
| 101 | // At beginning of file |
| 102 | #include <pybind11/eval.h> |
| 103 | |
| 104 | ... |
| 105 | |
| 106 | // Evaluate in scope of main module |
Henry Schreiner | 6bcd220 | 2020-10-03 13:38:03 -0400 | [diff] [blame] | 107 | py::object scope = py::module_::import("__main__").attr("__dict__"); |
Dean Moldovan | 67b52d8 | 2016-10-16 19:12:43 +0200 | [diff] [blame] | 108 | |
| 109 | // Evaluate an isolated expression |
| 110 | int result = py::eval("my_variable + 10", scope).cast<int>(); |
| 111 | |
| 112 | // Evaluate a sequence of statements |
Dean Moldovan | 076c738 | 2017-04-30 01:53:06 +0200 | [diff] [blame] | 113 | py::exec( |
Dean Moldovan | 67b52d8 | 2016-10-16 19:12:43 +0200 | [diff] [blame] | 114 | "print('Hello')\n" |
| 115 | "print('world!');", |
| 116 | scope); |
| 117 | |
| 118 | // Evaluate the statements in an separate Python file on disk |
| 119 | py::eval_file("script.py", scope); |
Dean Moldovan | 194d8b9 | 2017-03-29 00:27:56 +0200 | [diff] [blame] | 120 | |
| 121 | C++11 raw string literals are also supported and quite handy for this purpose. |
| 122 | The only requirement is that the first statement must be on a new line following |
| 123 | the raw string delimiter ``R"(``, ensuring all lines have common leading indent: |
| 124 | |
| 125 | .. code-block:: cpp |
| 126 | |
Dean Moldovan | 076c738 | 2017-04-30 01:53:06 +0200 | [diff] [blame] | 127 | py::exec(R"( |
Dean Moldovan | 194d8b9 | 2017-03-29 00:27:56 +0200 | [diff] [blame] | 128 | x = get_answer() |
| 129 | if x == 42: |
| 130 | print('Hello World!') |
| 131 | else: |
| 132 | print('Bye!') |
| 133 | )", scope |
| 134 | ); |
Dean Moldovan | 076c738 | 2017-04-30 01:53:06 +0200 | [diff] [blame] | 135 | |
| 136 | .. note:: |
| 137 | |
| 138 | `eval` and `eval_file` accept a template parameter that describes how the |
| 139 | string/file should be interpreted. Possible choices include ``eval_expr`` |
| 140 | (isolated expression), ``eval_single_statement`` (a single statement, return |
| 141 | value is always ``none``), and ``eval_statements`` (sequence of statements, |
| 142 | return value is always ``none``). `eval` defaults to ``eval_expr``, |
| 143 | `eval_file` defaults to ``eval_statements`` and `exec` is just a shortcut |
| 144 | for ``eval<eval_statements>``. |