Search code examples
c++python-3.xboostboost-python

Should I throw away the return value of boost::python::exec?


I'm writing a program with C++ and boost::python, and it seems very strange to me that boost::python::exec returns anything at all. For example, in the docs here, it says:

Effects

Execute Python source code from code in the context specified by the dictionaries globals and locals.

Returns

An instance of object which holds the result of executing the code.

And yet the documentation for python 3's exec function says that:

The return value is None.

So what's the point of returning anything if the function always returns none? Why not just make it a void function, or even better yet, have it return a python error if something goes wrong? Or maybe, I'm just misunderstanding the documentation, and there is something useful in there after all. Which is why I'm asking this question.

As I was trying to figure this out, I tried this sample program:

#include <boost\python.hpp>
#include <iostream>

int main()
{
    using namespace boost::python;

    Py_Initialize();

    object main_module = import("__main__");
    object main_namespace = main_module.attr("__dict__");

    while (true)
    {
        try
        {
            std::cout << ">>> ";
            std::string comm;
            std::getline(std::cin, comm);
            if (comm == "exit")
                break;
            object bar = exec(comm.c_str(), main_namespace);
            if (bar.is_none())
                std::cout << "None\n";
        }
        catch (error_already_set const &)
        {
            PyErr_Print();
        }
    }
}

And it seems like exec never returned an object that isn't None.

So is there ever, under any circumstance a reason to keep around the return value of a boost::python::exec call, or should I just always throw it away?


Solution

  • The concept of a void function in Python is one with no return value. If you attempt to assign the result of a void function, the result will always be None.

    Boost::Python seems to follow this in their implementation of py::exec, although this is no surprise as even the CPython PyRun_String function that py::exec calls returns a PyObject that is always None.

    So to answer your question, yes you can ignore the return value.