这是Boost :: Python(Python 3.7)错误"__init __()应该返回None,而不是'NoneType'"吗?链接问题? [英] Is this Boost::Python (Python 3.7) error "__init__() should return None, not 'NoneType'" a linking problem?

查看:66
本文介绍了这是Boost :: Python(Python 3.7)错误"__init __()应该返回None,而不是'NoneType'"吗?链接问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于我在技术上还没有解决问题,因此我不会将其添加为答案.但是,由于我现在花了2.5天的时间来尝试让boost-python3正常运行,所以我失去了使用它的意愿.

I'm not going to add this as an answer, since I still haven't technically solved the problem. But since I've now spent 2.5 days trying to get things to work with boost-python3, I've lost the will to live with it.

我刚刚遇到 pybind11 (我以前冗长的python绑定工具搜索是怎么做的?不能打开它,我不知道),并且正在使用它. 2.5天的苦难与安装和构建其 cmake示例的时间不到20分钟...特定的python-version-dependency-hell消失了.

I've just come across pybind11 (how my previous lengthy searches for python binding tools didn't turn it up, I don't know) and am using that. 2.5 days of misery compares to <20 minutes installing and building their cmake example... and all the specific-python-version-dependency-hell is gone.

从语法上讲,它与boost-python类似,但更易于管理,更快,仅标头且功能更丰富.

It's syntactically similar to boost-python but much easier to manage, quicker, is header-only and is more feature rich.

是的!

我正在使用boost :: python绑定python 3.7.2中的类.

I'm using boost::python to bind a class in python 3.7.2.

该类导入成功,但实例化该类时出现以下错误:

The class import successfully but instantiating it gives the following error:

<my-terminal>$ python
Python 3.7.2 (default, Feb 14 2019, 17:36:47) 
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import classes
>>> t = classes.World()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() should return None, not 'NoneType'
>>> 

这里是classes.cpp:

#include <boost/python.hpp>
#include <boost/python/list.hpp>
#include <boost/python/extract.hpp>
#include <string>
#include <sstream>
#include <vector>

struct World
{
    void set(std::string msg) { mMsg = msg; }
    void many(boost::python::list msgs) {
        long l = len(msgs);
        std::stringstream ss;
        for (long i = 0; i<l; ++i) {
            if (i>0) ss << ", ";
            std::string s = boost::python::extract<std::string>(msgs[i]);
            ss << s;
        }
        mMsg = ss.str();
    }
    std::string greet() { return mMsg; }
    std::string mMsg;
};

using namespace boost::python;

BOOST_PYTHON_MODULE(classes)
{
    class_<World>("World")
        .def("greet", &World::greet)
        .def("set", &World::set)
        .def("many", &World::many)
    ;
};

假设

几乎完全相同的问题由于以下原因得以解决: python 2/3问题(链接到python 3而不是python 2库).所以我怀疑是图书馆链接问题.

Hypothesis

This question, almost identical was solved because of a python 2/3 issue (linking against python 3 instead of python 2 libraries). So I suspected a library linking issue.

我无法使bjam正常工作,也无法将所有构建系统切换为一个模块...因此,我正在使用cmake进行构建,它将成功编译为classes.so,其输出如下所示,建议我找到所有正确的包含库,可执行文件:

I can't get bjam to work, and wouldn't be able to switch all our build systems over for one module anyway... so am building with cmake, which compiles successfully to classes.so with output as follows, suggesting I'm finding all the correct includes, libraries and executables:

-- Found PythonInterp: /Users/me/.pyenv/versions/boost37/bin/python3 (found suitable version "3.7.2", minimum required is "3") 
PYTHON_VERSION_SUFFIX
-- Boost version: 1.68.0
-- Found the following Boost libraries:
--   python37
-- Found PythonLibs: /usr/local/Frameworks/Python.framework/Versions/3.7/lib/libpython3.7m.dylib (found suitable version "3.7.2", minimum required is "3") 
-- PYTHON_LIBRARIES = /usr/local/Frameworks/Python.framework/Versions/3.7/lib/libpython3.7m.dylib
-- PYTHON_EXECUTABLE = /Users/thc29/.pyenv/versions/boost37/bin/python3
-- PYTHON_INCLUDE_DIRS = /usr/local/Frameworks/Python.framework/Versions/3.7/include/python3.7m
-- Boost_LIBRARIES = /usr/local/lib/libboost_python37-mt.dylib

Boost-python3库目录内容:

Boost-python3 library directory contents:

ls /usr/local/Cellar/boost-python3/1.68.0/lib
libboost_numpy37-mt.a       libboost_numpy37.dylib      libboost_python37.a
libboost_numpy37-mt.dylib   libboost_python37-mt.a      libboost_python37.dylib
libboost_numpy37.a      libboost_python37-mt.dylib

我使用brew install boostbrew install boost-python3 --build-from-source并激活了python 3.7 virtualenv,以确保boost-python3与正确版本的python链接.

I used brew install boost, and brew install boost-python3 --build-from-source with my python 3.7 virtualenv activated, to ensure boost-python3 is linked against the correct version of python.

正在检查库...

otool -L classes.so给出:

classes.so:
    /usr/l/opt/boost-python3/lib/libboost_python37-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
    /usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/Python (compatibility version 3.7.0, current version 3.7.0)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)

otool -L /usr/local/opt/boost-python3/lib/libboost_python37-mt.dylib给出:

/usr/local/opt/boost-python3/lib/libboost_python37-mt.dylib:
        /usr/local/opt/boost-python3/lib/libboost_python37-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)

在相关问题中,这表明了他们的问题.但是在这里看起来不错!

In the related question, that showed their problem. But here it appears fine!

经过痛苦的过程,正确地进行了所有编译并检查了链接,我看不到任何缺陷.这是一个不同的问题吗?还是存在我未发现的链接问题?

After the painful process of getting this all compiling properly and checking the linking, I can't spot any flaws. Is this a different problem? Or is there a linking issue that I haven't spotted?

感谢您的帮助!

推荐答案

我正在跟踪

I am following a similar example and I adopt the Makefile from here. I have installed python 3.7.4 and boost-python via brew on macOS. To fix the NoneType issue, I follow the procedure below:

1.检查Python路径
要检查python路径,请使用

1. Check the Python Path
To check the python path, use

which python

如果输出看起来不像以下内容(brewpython安装路径)

If the output does not look like the following one (brew's python installation path)

/usr/local/opt/python/libexec/bin/python

PATH变量设置为

export PATH="/usr/local/opt/python/libexec/bin:$PATH"

再次检查Python路径是否类似于上面的路径.

Check if the Python path looks like the one above again.

2.检查编译标志
下面是采用的Makefile.注意LIB变量.如果boost-python标志是-lboost_python,请将其更改为-lboost_python37.

2. Check the Compilation Flag
Below is the adopted Makefile. Note the LIB variable. If the boost-python flag is -lboost_python, change it to -lboost_python37.

CPP = clang++
PYLIBPATH = $(shell python-config --exec-prefix)/lib
# LIB = -L$(PYLIBPATH) $(shell python-config --libs) -lboost_python
LIB = -L$(PYLIBPATH) $(shell python-config --libs) -lboost_python37
OPTS = $(shell python-config --include) -O2

default: hello.so


hello.so: hello.o
    $(CPP) $(LIB) -Wl,-rpath,$(PYLIBPATH) -shared $< -o $@

hello.o: hello.cpp Makefile
    $(CPP) $(OPTS) -c $< -o $@

clean:
    rm -rf *.so *.o

.PHONY: default clean

重新编译C++代码并运行python脚本. NoneType问题应该消失.

Recompile the C++ code and run the python script. The NoneType issue should disappear.

希望这会有所帮助.

注意
如果您使用的是anaconda,并且想在上述更改后恢复PATH变量,请尝试

Note
If you are using anaconda and want to restore the PATH variable after the above changes, try

export PATH="~/anaconda3/bin:$PATH"

您的anaconda的路径可能不同.

信用
1.
中的 leiyc 评论ld:在MacOS上找不到-lboost_python的库

Credit
1. George's comment in How do I use brew installed Python as the default Python?
2. leiyc's comment in ld: library not found for -lboost_python on MacOS

这篇关于这是Boost :: Python(Python 3.7)错误"__init __()应该返回None,而不是'NoneType'"吗?链接问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆