这是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?
问题描述
由于我在技术上还没有解决问题,因此我不会将其添加为答案.但是,由于我现在花了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 boost
和brew 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?
感谢您的帮助!
推荐答案
我正在跟踪此处.我已经通过macOS
上的brew
安装了python 3.7.4
和boost-python
.要解决NoneType
问题,请按照以下步骤操作:
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
如果输出看起来不像以下内容(brew
的python
安装路径)
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屋!