代码之家  ›  专栏  ›  技术社区  ›  Sahas

如何在boost::python嵌入式python代码中导入模块?

  •  11
  • Sahas  · 技术社区  · 15 年前

    我正在使用boost::python将一些python代码嵌入到应用程序中。我能够让print语句或其他表达式得到正确的计算结果,但是当我尝试导入模块时,它没有导入,应用程序正在退出。此外,嵌入代码中的globals()函数调用也会产生运行时错误。

    #include <boost/python.hpp>
    
    using namespace boost;
    using namespace boost::python;
    using namespace boost::python::api;
    
    int main(void) {
        Py_Initialize();
        object main_module = import("__main__");
        object main_namespace = main_module.attr("__dict__");
        main_namespace["urllib2"] = import("urllib2");
    
        object ignored = exec(
                "print 'time'\n", main_namespace);
    }
    

    在这里,我尝试使用boost import函数导入urlib2,这可以正确编译和运行,但是使用下面的exec语句,它会给出一个错误。

        object ignored = exec(
                "print urllib2\n"
                "print 'time'\n", main_namespace);
    

    或者,当我移除boost导入函数并从嵌入的代码中进行导入时,它会给出一个错误。我试过试一下:除了:挡块,但也不管用。这是因为C++应用程序无法找到URLLIB2 PY模块的位置吗?在尝试导入之前,是否有方法设置模块的路径?

    这只是为内部使用而构建的,所以可以接受对路径进行一些硬编码。

    编辑:更多信息:
    这就是发生的事情。我试了一下……捕获并在出现异常时调用pyerr_print(),并在有模块导入甚至函数调用时一直将其作为错误获取。错误消息:

    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    TypeError: 'NoneType' object does not support item assignment
    

    有人能想出什么理由吗?

    3 回复  |  直到 15 年前
        1
  •  5
  •   Jonas Byström    15 年前

    如果你还没有,你需要

    import sys
    sys.path.append("/home/user/whatever")
    

    几年前嵌入boost::python(python v2.5)时,我的问题就解决了。

    编辑:

    用旧密码到处翻。也许这就是诀窍:

    Py_SetProgramName(argv[0]);
    Py_InitializeEx(0);
    

    听起来不确定你是否真的需要 Py_SetProgramName() 但我隐约记得那里的一些可疑的事情。

        2
  •  3
  •   Sahas    15 年前

    这没用,但我找到了一个不同的解决方法。我当前的代码如下:

    #include <boost/python.hpp>
    #include <iostream>
    
    using namespace std;
    using namespace boost;
    using namespace boost::python;
    using namespace boost::python::api;
    
    int main(void) {
            Py_Initialize();
            boost::python::object http = boost::python::import("urllib2");
    
            try
            {
                    boost::python::object response = http.attr("urlopen")("http://www.google.com");
                    boost::python::object read = response.attr("read")();
                    std::string strResponse = boost::python::extract<string>(read);
                    cout << strResponse << endl;
            }
            catch(...)
            {
                    PyErr_Print();
                    PyErr_Clear();
            }
    }
    

    不管怎样,谢谢乔纳斯的回答

        3
  •  0
  •   Community Egal    7 年前

    我遇到了和你一样的问题,我是一个非常简单的例子,导致了类型错误,并在 this question ,它将两次提供命名空间,包括全局和本地。