Blame external/pybind11/docs/advanced/pycpp/utilities.rst

Packit 534379
Utilities
Packit 534379
#########
Packit 534379
Packit 534379
Using Python's print function in C++
Packit 534379
====================================
Packit 534379
Packit 534379
The usual way to write output in C++ is using ``std::cout`` while in Python one
Packit 534379
would use ``print``. Since these methods use different buffers, mixing them can
Packit 534379
lead to output order issues. To resolve this, pybind11 modules can use the
Packit 534379
:func:`py::print` function which writes to Python's ``sys.stdout`` for consistency.
Packit 534379
Packit 534379
Python's ``print`` function is replicated in the C++ API including optional
Packit 534379
keyword arguments ``sep``, ``end``, ``file``, ``flush``. Everything works as
Packit 534379
expected in Python:
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    py::print(1, 2.0, "three"); // 1 2.0 three
Packit 534379
    py::print(1, 2.0, "three", "sep"_a="-"); // 1-2.0-three
Packit 534379
Packit 534379
    auto args = py::make_tuple("unpacked", true);
Packit 534379
    py::print("->", *args, "end"_a="<-"); // -> unpacked True <-
Packit 534379
Packit 534379
.. _ostream_redirect:
Packit 534379
Packit 534379
Capturing standard output from ostream
Packit 534379
======================================
Packit 534379
Packit 534379
Often, a library will use the streams ``std::cout`` and ``std::cerr`` to print,
Packit 534379
but this does not play well with Python's standard ``sys.stdout`` and ``sys.stderr``
Packit 534379
redirection. Replacing a library's printing with `py::print <print>` may not
Packit 534379
be feasible. This can be fixed using a guard around the library function that
Packit 534379
redirects output to the corresponding Python streams:
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    #include <pybind11/iostream.h>
Packit 534379
Packit 534379
    ...
Packit 534379
Packit 534379
    // Add a scoped redirect for your noisy code
Packit 534379
    m.def("noisy_func", []() {
Packit 534379
        py::scoped_ostream_redirect stream(
Packit 534379
            std::cout,                               // std::ostream&
Packit 534379
            py::module::import("sys").attr("stdout") // Python output
Packit 534379
        );
Packit 534379
        call_noisy_func();
Packit 534379
    });
Packit 534379
Packit 534379
This method respects flushes on the output streams and will flush if needed
Packit 534379
when the scoped guard is destroyed. This allows the output to be redirected in
Packit 534379
real time, such as to a Jupyter notebook. The two arguments, the C++ stream and
Packit 534379
the Python output, are optional, and default to standard output if not given. An
Packit 534379
extra type, `py::scoped_estream_redirect <scoped_estream_redirect>`, is identical
Packit 534379
except for defaulting to ``std::cerr`` and ``sys.stderr``; this can be useful with
Packit 534379
`py::call_guard`, which allows multiple items, but uses the default constructor:
Packit 534379
Packit 534379
.. code-block:: py
Packit 534379
Packit 534379
    // Alternative: Call single function using call guard
Packit 534379
    m.def("noisy_func", &call_noisy_function,
Packit 534379
          py::call_guard
Packit 534379
                         py::scoped_estream_redirect>());
Packit 534379
Packit 534379
The redirection can also be done in Python with the addition of a context
Packit 534379
manager, using the `py::add_ostream_redirect() <add_ostream_redirect>` function:
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    py::add_ostream_redirect(m, "ostream_redirect");
Packit 534379
Packit 534379
The name in Python defaults to ``ostream_redirect`` if no name is passed.  This
Packit 534379
creates the following context manager in Python:
Packit 534379
Packit 534379
.. code-block:: python
Packit 534379
Packit 534379
    with ostream_redirect(stdout=True, stderr=True):
Packit 534379
        noisy_function()
Packit 534379
Packit 534379
It defaults to redirecting both streams, though you can use the keyword
Packit 534379
arguments to disable one of the streams if needed.
Packit 534379
Packit 534379
.. note::
Packit 534379
Packit 534379
    The above methods will not redirect C-level output to file descriptors, such
Packit 534379
    as ``fprintf``. For those cases, you'll need to redirect the file
Packit 534379
    descriptors either directly in C or with Python's ``os.dup2`` function
Packit 534379
    in an operating-system dependent way.
Packit 534379
Packit 534379
.. _eval:
Packit 534379
Packit 534379
Evaluating Python expressions from strings and files
Packit 534379
====================================================
Packit 534379
Packit 534379
pybind11 provides the `eval`, `exec` and `eval_file` functions to evaluate
Packit 534379
Python expressions and statements. The following example illustrates how they
Packit 534379
can be used.
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    // At beginning of file
Packit 534379
    #include <pybind11/eval.h>
Packit 534379
Packit 534379
    ...
Packit 534379
Packit 534379
    // Evaluate in scope of main module
Packit 534379
    py::object scope = py::module::import("__main__").attr("__dict__");
Packit 534379
Packit 534379
    // Evaluate an isolated expression
Packit 534379
    int result = py::eval("my_variable + 10", scope).cast<int>();
Packit 534379
Packit 534379
    // Evaluate a sequence of statements
Packit 534379
    py::exec(
Packit 534379
        "print('Hello')\n"
Packit 534379
        "print('world!');",
Packit 534379
        scope);
Packit 534379
Packit 534379
    // Evaluate the statements in an separate Python file on disk
Packit 534379
    py::eval_file("script.py", scope);
Packit 534379
Packit 534379
C++11 raw string literals are also supported and quite handy for this purpose.
Packit 534379
The only requirement is that the first statement must be on a new line following
Packit 534379
the raw string delimiter ``R"(``, ensuring all lines have common leading indent:
Packit 534379
Packit 534379
.. code-block:: cpp
Packit 534379
Packit 534379
    py::exec(R"(
Packit 534379
        x = get_answer()
Packit 534379
        if x == 42:
Packit 534379
            print('Hello World!')
Packit 534379
        else:
Packit 534379
            print('Bye!')
Packit 534379
        )", scope
Packit 534379
    );
Packit 534379
Packit 534379
.. note::
Packit 534379
Packit 534379
    `eval` and `eval_file` accept a template parameter that describes how the
Packit 534379
    string/file should be interpreted. Possible choices include ``eval_expr``
Packit 534379
    (isolated expression), ``eval_single_statement`` (a single statement, return
Packit 534379
    value is always ``none``), and ``eval_statements`` (sequence of statements,
Packit 534379
    return value is always ``none``). `eval` defaults to  ``eval_expr``,
Packit 534379
    `eval_file` defaults to ``eval_statements`` and `exec` is just a shortcut
Packit 534379
    for ``eval<eval_statements>``.