pybind11使用教程笔记__5.3_python C++ interface__Utilities

1. Using Python’s print function in C++

C++ 输出使用 std::cout, python 使用print。两种方法使用不同的buffers,混合可以导致 output order issues。为了解决这个问题,pybind11 module 提供了py::print 将输出流传递给python sys.stdout.
Python’s print function is replicated in the C++ API including optional keyword arguments sep, end, file, flush. Everything works as expected in Python:

py::print(1, 2.0, "three"); // 1 2.0 three
py::print(1, 2.0, "three", "sep"_a="-"); // 1-2.0-three

auto args = py::make_tuple("unpacked", true);
py::print("->", *args, "end"_a="<-"); // -> unpacked True <-

2. Capturing standard output from ostream

Often, a library will use the streams std::cout and std::cerr to print, but this does not play well with Python’s standard sys.stdout and sys.stderr redirection.
Replacing a library’s printing with py::print may not be feasible. This can be fixed using a guard around the library function that redirects output to the corresponding Python streams:

将C++module中的所有std::cout quan全部替换为python print恐怕不太现实,C++输出重定向至python可以通过 a guard around the library function 实现。

#include <pybind11/iostream.h>

...

// Add a scoped redirect for your noisy code
m.def("noisy_func", []() {
    py::scoped_ostream_redirect stream(
        std::cout,                               // std::ostream&
        py::module::import("sys").attr("stdout") // Python output
    );
    call_noisy_func();
});

This method respects flushes on the output streams and will flush if needed when the scoped guard is destroyed.
这个允许输出重定向实时化,比如重定向至Jupyter Notebook。
两个可选参数(C++ stream和python output), 为默认的标准输出流,如果这两个参数没有给定。
An extra type, py::scoped_estream_redirect, is identical except for defaulting to std::cerr and sys.stderr;
this can be useful with py::call_guard, which allows multiple items, but uses the default constructor:

// Alternative: Call single function using call guard
m.def("noisy_func", &call_noisy_function,
      py::call_guard<py::scoped_ostream_redirect,
                     py::scoped_estream_redirect>());

重定向也可以在python中完成,添加上下文管理(context manager),using the py::add_ostream_redirect() function:

py::add_ostream_redirect(m, "ostream_redirect");

python中默认名为ostream_redirect,会在python中创建如下的上下文管理器。默认会对两个流均进行重定向,也可以只对其中一个流进行重定向。

with ostream_redirect(stdout=True, stderr=True):
    noisy_function()

Note

上述的方法不会对C/C++中的文件的输出流进行重定向,比如fprintf。
这种情境下需要直接在C中进行重定向,或者在python中重定向使用 os.dup2 function in an operating-system dependent way.

3. Evaluating Python expressions from strings and files

pybind11 提供eval, exec and eval_file functions 来执行python语句表达式和文件,如下例:

// At beginning of file
#include <pybind11/eval.h>

...

// Evaluate in scope of main module
py::object scope = py::module::import("__main__").attr("__dict__");

// Evaluate an isolated expression
int result = py::eval("my_variable + 10", scope).cast<int>();

// Evaluate a sequence of statements
py::exec(
    "print('Hello')\n"
    "print('world!');",
    scope);

// Evaluate the statements in an separate Python file on disk
py::eval_file("script.py", scope);

C++11 raw string literals are also supported and quite handy for this purpose. The only requirement is that the first statement must be on a new line following the raw string delimiter R"(, ensuring all lines have common leading indent:

py::exec(R"(
    x = get_answer()
    if x == 42:
        print('Hello World!')
    else:
        print('Bye!')
    )", scope
);

Note

eval and eval_file 有一个模板参数,该参数描述了这些string/file应该如何被interpreted。
可能的选项:

  • eval_expr (isolated expression),
  • eval_single_statement (a single statement, return value is always none)
  • eval_statements (sequence of statements, return value is always none).

eval defaults to eval_expr,
eval_file defaults to eval_statements
exec is just a shortcut for eval<eval_statements>.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值