如何打印boost.python中的自定义python类型

发布于 2025-01-31 02:48:00 字数 4564 浏览 2 评论 0 原文

我正在尝试使用boost.python库,以便从Python Skyfield API中获取数据,但是我很难打印出数据。该程序运行,但我会收到此错误:“ python中的错误:< class'typeError'>:'nontype'对象无法callable”。

正确的输出应该显示这样的东西: 10h 47m 56.24s +09DEG 03'23.1” 2.33251 AU

我正在使用本网站上的第一个代码示例作为参考: https://rhodesmill.org.org/skyfield/skyfield/skyfield/

如果您对如何正确输出数据有任何想法,请告诉我!

到目前为止,这是我的代码:

#include <iostream>
#include <boost/python.hpp>
#include <Python.h>

namespace py = boost::python;

std::string parse_python_exception();

int main()
{
    Py_Initialize(); //Initializes the Python interpreter

    //Imports the __main__ module and extracts the namespace
    //This creates a blank 'canvas' upon which we can call Python code
    py::object main_module = py::import("__main__");

    //Loads the dictionary object from the main module
    py::object main_namespace = main_module.attr("__dict__");

    try
    {
        //Imports
        py::exec("from skyfield.api import load");
        py::object skyfield_mod = py::import("skyfield.api");
        py::object skyfield_load = skyfield_mod.attr("load");
        py::object skyfield_load_timescale = skyfield_load.attr("timescale");

        py::exec("print('This program computes the current position of Mars in the sky')", main_namespace);

        py::object ts = skyfield_load_timescale();

        py::object ts_now = ts.attr("now");

        py::object t = ts_now();

        py::object planets = skyfield_load("de421.bsp");
        py::object earth = planets["earth"];
        py::object mars = planets["mars"];

        py::object earth_at = earth.attr("at");

        py::object earth_at_observe = earth_at(t).attr("observe");

        py::object m_earth_at_observe = earth_at_observe(mars);
        
        py::object astrometric = m_earth_at_observe;

        py::object ra, dec, distance = astrometric.attr("radec");

        py::object m_ra = ra();
        py::object m_dec = dec();
        py::object m_distance = distance();

        py::exec("print(m_ra)", main_namespace);
    }
    catch (boost::python::error_already_set const&)
    {
        std::string perror_str = parse_python_exception();
        std::cout << "Error in Python: " << perror_str << std::endl;
    }
}

// Parses the value of the active python exception
// NOTE SHOULD NOT BE CALLED IF NO EXCEPTION
std::string parse_python_exception() {
    PyObject* type_ptr = NULL, * value_ptr = NULL, * traceback_ptr = NULL;
    // Fetch the exception info from the Python C API
    PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr);

    // Fallback error
    std::string ret("Unfetchable Python error");
    // If the fetch got a type pointer, parse the type into the exception string
    if (type_ptr != NULL) {
        py::handle<> h_type(type_ptr);
        py::str type_pstr(h_type);
        // Extract the string from the boost::python object
        py::extract<std::string> e_type_pstr(type_pstr);
        // If a valid string extraction is available, use it 
        //  otherwise use fallback
        if (e_type_pstr.check())
            ret = e_type_pstr();
        else
            ret = "Unknown exception type";
    }
    // Do the same for the exception value (the stringification of the exception)
    if (value_ptr != NULL) {
        py::handle<> h_val(value_ptr);
        py::str a(h_val);
        py::extract<std::string> returned(a);
        if (returned.check())
            ret += ": " + returned();
        else
            ret += std::string(": Unparseable Python error: ");
    }
    // Parse lines from the traceback using the Python traceback module
    if (traceback_ptr != NULL) {
        py::handle<> h_tb(traceback_ptr);
        // Load the traceback module and the format_tb function
        py::object tb(py::import("traceback"));
        py::object fmt_tb(tb.attr("format_tb"));
        // Call format_tb to get a list of traceback strings
        py::object tb_list(fmt_tb(h_tb));
        // Join the traceback strings into a single string
        py::object tb_str(py::str("\n").join(tb_list));
        // Extract the string, check the extraction, and fallback in necessary
        py::extract<std::string> returned(tb_str);
        if (returned.check())
            ret += ": " + returned();
        else
            ret += std::string(": Unparseable Python traceback");
    }
    return ret;
}

I am trying to use the boost.python library in order to get data from the Python skyfield API, but I am having trouble printing out the data. The program runs, but I get this error: "Error in Python: <class 'TypeError'>: 'NoneType' object is not callable"

The correct output should show something like this:
10h 47m 56.24s
+09deg 03' 23.1"
2.33251 au

I am using the first code example from this website as a reference: https://rhodesmill.org/skyfield/

If you have any ideas on how to get the data to correctly output, please let me know!

Here is my code so far:

#include <iostream>
#include <boost/python.hpp>
#include <Python.h>

namespace py = boost::python;

std::string parse_python_exception();

int main()
{
    Py_Initialize(); //Initializes the Python interpreter

    //Imports the __main__ module and extracts the namespace
    //This creates a blank 'canvas' upon which we can call Python code
    py::object main_module = py::import("__main__");

    //Loads the dictionary object from the main module
    py::object main_namespace = main_module.attr("__dict__");

    try
    {
        //Imports
        py::exec("from skyfield.api import load");
        py::object skyfield_mod = py::import("skyfield.api");
        py::object skyfield_load = skyfield_mod.attr("load");
        py::object skyfield_load_timescale = skyfield_load.attr("timescale");

        py::exec("print('This program computes the current position of Mars in the sky')", main_namespace);

        py::object ts = skyfield_load_timescale();

        py::object ts_now = ts.attr("now");

        py::object t = ts_now();

        py::object planets = skyfield_load("de421.bsp");
        py::object earth = planets["earth"];
        py::object mars = planets["mars"];

        py::object earth_at = earth.attr("at");

        py::object earth_at_observe = earth_at(t).attr("observe");

        py::object m_earth_at_observe = earth_at_observe(mars);
        
        py::object astrometric = m_earth_at_observe;

        py::object ra, dec, distance = astrometric.attr("radec");

        py::object m_ra = ra();
        py::object m_dec = dec();
        py::object m_distance = distance();

        py::exec("print(m_ra)", main_namespace);
    }
    catch (boost::python::error_already_set const&)
    {
        std::string perror_str = parse_python_exception();
        std::cout << "Error in Python: " << perror_str << std::endl;
    }
}

// Parses the value of the active python exception
// NOTE SHOULD NOT BE CALLED IF NO EXCEPTION
std::string parse_python_exception() {
    PyObject* type_ptr = NULL, * value_ptr = NULL, * traceback_ptr = NULL;
    // Fetch the exception info from the Python C API
    PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr);

    // Fallback error
    std::string ret("Unfetchable Python error");
    // If the fetch got a type pointer, parse the type into the exception string
    if (type_ptr != NULL) {
        py::handle<> h_type(type_ptr);
        py::str type_pstr(h_type);
        // Extract the string from the boost::python object
        py::extract<std::string> e_type_pstr(type_pstr);
        // If a valid string extraction is available, use it 
        //  otherwise use fallback
        if (e_type_pstr.check())
            ret = e_type_pstr();
        else
            ret = "Unknown exception type";
    }
    // Do the same for the exception value (the stringification of the exception)
    if (value_ptr != NULL) {
        py::handle<> h_val(value_ptr);
        py::str a(h_val);
        py::extract<std::string> returned(a);
        if (returned.check())
            ret += ": " + returned();
        else
            ret += std::string(": Unparseable Python error: ");
    }
    // Parse lines from the traceback using the Python traceback module
    if (traceback_ptr != NULL) {
        py::handle<> h_tb(traceback_ptr);
        // Load the traceback module and the format_tb function
        py::object tb(py::import("traceback"));
        py::object fmt_tb(tb.attr("format_tb"));
        // Call format_tb to get a list of traceback strings
        py::object tb_list(fmt_tb(h_tb));
        // Join the traceback strings into a single string
        py::object tb_str(py::str("\n").join(tb_list));
        // Extract the string, check the extraction, and fallback in necessary
        py::extract<std::string> returned(tb_str);
        if (returned.check())
            ret += ": " + returned();
        else
            ret += std::string(": Unparseable Python traceback");
    }
    return ret;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文