【问题标题】:synthesized submodule: from A import B (ok) vs. import A.B (error)?合成子模块:从 A 导入 B(正常)与导入 A.B(错误)?
【发布时间】:2012-06-19 06:22:27
【问题描述】:

我有一个模块modA,其中包含一个合成子模块modB(用PyModule_New创建);现在导入模块:

  1. from modA import modB没关系
  2. import modA.modB 失败。

我错过了什么?

  • modA.cpp(使用boost::python,但很可能与纯python的c-API相同):

    #include<boost/python.hpp>
    namespace py=boost::python;
    
    BOOST_PYTHON_MODULE(modA){
       py::object modB=py::object(py::handle<>(PyModule_New("modB")));
       modB.attr("__file__")="<synthetic>";
       py::scope().attr("modB")=modB;
    };
    
  • 使用(g++ 而不是 clang++ 的编译方式相同)

    clang++ -o modA.so modA.cpp -fPIC -shared  -lboost_python `pkg-config python --cflags --libs`
    
  • test.py:

    import sys
    sys.path.append('.')
    from modA import modB
    import modA.modB
    
  • python test.py(注意第一次导入没问题,第二次导入失败):

    Traceback (most recent call last):
      File "test.py", line 4, in <module>
        import modA.modB
    ImportError: No module named modB
    

【问题讨论】:

  • 您应该添加您的解决方案作为答案并接受它。
  • 我刚做了,谢谢你的建议。必须等待 2 天才能接受它:-)

标签: python boost-python python-module synthetic


【解决方案1】:

感谢this answer,我找到了解决方案,包含在sys.modules['modA.modB']=modB中,但是在模块初始化函数中用c++写的:

#include<boost/python.hpp>
namespace py=boost::python;

BOOST_PYTHON_MODULE(modA){
   py::object modB=py::object(py::handle<>(PyModule_New("modA.modB")));
   modB.attr("__file__")="<synthetic>";
   py::scope().attr("modB")=modB;

   // this was the missing piece: sys.modules['modA.modB']=modB
   py::extract<py::dict>(py::getattr(py::import("sys"),"modules"))()["modA.modB"]=modB;
};

【讨论】:

    【解决方案2】:

    这是我使用的模式,希望它能改进以前的答案...

    模块.h:

    ...
    #define STR(str) #str
    #define MAKE_SUBMODULE(mod, submod) object submod##_module(handle<>(borrowed(PyImport_AddModule(STR(mod.submod)))));\
    scope().attr(STR(submod)) = submod##_module;\
    scope submod##_scope = submod##_module;\
    ...
    export_submodule();
    ...
    

    模块.cpp:

    BOOST_PYTHON_MODULE(modulename)
    {
        export_submodule();
    }
    

    子模块.cpp:

    export_submodule()
    {
        // create submodule
        MAKE_SUBMODULE(modulename, submodulename)
    
        // all code below is now in submodule's scope
        ...
    }
    

    “生成”的代码如下所示:

    object submodulename_module(handle<>(borrowed(PyImport_AddModule("modulename.submodulename"))));
    scope().attr("submodulename") = submodulename_module;
    scope submodulename_scope = submodulename_module;
    

    它看起来类似于 eudoxos 的答案,但差异似乎很详细:我使用 PyImportAdd() 而不是 PyImportNew()。因此,我不需要最后一行来使 from module.submodule import * 语句正常工作。

    【讨论】:

      【解决方案3】:

      modB 不是文件(即模块),而是modA 中的某个对象,因此无法导入。

      你可能想看看Python's modules docs

      【讨论】:

      • modB 是一个模块,它恰好是动态创建的。
      • 我不明白。请说明 - modB 是不是一个文件?
      • 不,modB 是在运行时创建的模块对象。
      • imp.find_module 根据文档仅搜索文件。不过,很抱歉造成混淆,我同时找到了解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-20
      • 2010-11-16
      • 2015-10-06
      • 1970-01-01
      • 1970-01-01
      • 2021-12-08
      相关资源
      最近更新 更多