- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在调用 boost::python::import("cv2")
时抛出了异常 boost::python::error_already_set
首先,我写了一个python脚本pymod.py
:
import sys
...
并在cpp代码中使用boost::python
导入pymod.py
:
...
boost::python::import("pymod");
...
效果很好。
但是当我在 pymod.py
中添加 cv2
时:
import sys, cv2
boost::python::import("pymod")
抛出异常:
terminate called after throwing an instance of 'boost::python::error_already_set'
注意带有import cv2
的python脚本可以被python调用:
python pymod.py
没有错误。
所以我尝试了使用 boost::python
导入 cv2
的 cpp 版本,同样的异常被抛出。代码如下:
#include <boost/dll/import.hpp>
#include <boost/python.hpp>
int main(int nArgCnt, char *ppArgs[]) {
Py_Initialize();
boost::python::object pySys = boost::python::import("cv2");
return 0;
}
更新 1:
我还检查了源代码 boost_1_65_1/libs/python/src/import.cpp
并找到了 boost::python::import
的实现:
object BOOST_PYTHON_DECL import(str name)
{
// should be 'char const *' but older python versions don't use 'const' yet.
char *n = python::extract<char *>(name);
python::handle<> module(PyImport_ImportModule(n));
return python::object(module);
}
我尝试直接使用PyImport_ImportModule
,但也失败了:
#include <boost/dll/import.hpp>
#include <boost/python.hpp>
#include <Python.h>
#include <iostream>
int main(int nArgCnt, char *ppArgs[]) {
Py_Initialize();
// numpy, sys and other modules can be load! VERY STRANGE!!
auto pMod = PyImport_ImportModule("cv2");
std::cout << pMod << std::endl;
return 0;
}
此代码打印以下输出:
['/usr/local/lib/python3.6/dist-packages', '/usr/local/lib/python3.6/dist-packages/cv2/python-3.6', '/home/devymex/3rdparty/opencv-4.0.1/build/python_loader', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/home/devymex/.local/lib/python3.6/site-packages', '/usr/local/lib/python3.6/dist-packages/mxnet-1.3.1-py3.6.egg', '/usr/local/lib/python3.6/dist-packages/graphviz-0.8.4-py3.6.egg', '/usr/local/lib/python3.6/dist-packages/typing-3.6.6-py3.6.egg', '/usr/local/lib/python3.6/dist-packages/typing_extensions-3.6.6-py3.6.egg', '/usr/local/lib/python3.6/dist-packages/onnx-1.5.0-py3.6-linux-x86_64.egg', '/usr/lib/python3/dist-packages']
0
但我非常确定命令 python3 -c "import cv2"
没有问题。所以它似乎与提升无关。
更新 2:
PyErr_Print();
提供以下信息:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/cv2/__init__.py", line 89, in <module>
bootstrap()
File "/usr/local/lib/python3.6/dist-packages/cv2/__init__.py", line 79, in bootstrap
import cv2
File "/usr/local/lib/python3.6/dist-packages/cv2/__init__.py", line 89, in <module>
bootstrap()
File "/usr/local/lib/python3.6/dist-packages/cv2/__init__.py", line 23, in bootstrap
raise ImportError('ERROR: recursion is detected during loading of "cv2" binary extensions. Check OpenCV installation.')
ImportError: ERROR: recursion is detected during loading of "cv2" binary extensions. Check OpenCV installation.
__init__.py
:
'''
OpenCV Python binary extension loader
'''
import os
import sys
try:
import numpy
import numpy.core.multiarray
except ImportError:
print('OpenCV bindings requires "numpy" package.')
print('Install it via command:')
print(' pip install numpy')
raise
# TODO
# is_x64 = sys.maxsize > 2**32
def bootstrap():
import sys
if hasattr(sys, 'OpenCV_LOADER'):
print(sys.path)
raise ImportError('ERROR: recursion is detected during loading of "cv2" binary extensions. Check OpenCV installation.')
sys.OpenCV_LOADER = True
DEBUG = False
if hasattr(sys, 'OpenCV_LOADER_DEBUG'):
DEBUG = True
import platform
if DEBUG: print('OpenCV loader: os.name="{}" platform.system()="{}"'.format(os.name, str(platform.system())))
LOADER_DIR=os.path.dirname(os.path.abspath(__file__))
PYTHON_EXTENSIONS_PATHS = []
BINARIES_PATHS = []
g_vars = globals()
l_vars = locals()
if sys.version_info[:2] < (3, 0):
from cv2.load_config_py2 import exec_file_wrapper
else:
from . load_config_py3 import exec_file_wrapper
def load_first_config(fnames, required=True):
for fname in fnames:
fpath = os.path.join(LOADER_DIR, fname)
if not os.path.exists(fpath):
if DEBUG: print('OpenCV loader: config not found, skip: {}'.format(fpath))
continue
if DEBUG: print('OpenCV loader: loading config: {}'.format(fpath))
exec_file_wrapper(fpath, g_vars, l_vars)
return True
if required:
raise ImportError('OpenCV loader: missing configuration file: {}. Check OpenCV installation.'.format(fnames))
load_first_config(['config.py'], True)
load_first_config([
'config-{}.{}.py'.format(sys.version_info[0], sys.version_info[1]),
'config-{}.py'.format(sys.version_info[0])
], True)
if DEBUG: print('OpenCV loader: PYTHON_EXTENSIONS_PATHS={}'.format(str(l_vars['PYTHON_EXTENSIONS_PATHS'])))
if DEBUG: print('OpenCV loader: BINARIES_PATHS={}'.format(str(l_vars['BINARIES_PATHS'])))
for p in reversed(l_vars['PYTHON_EXTENSIONS_PATHS']):
sys.path.insert(1, p)
if os.name == 'nt':
os.environ['PATH'] = ';'.join(l_vars['BINARIES_PATHS']) + ';' + os.environ.get('PATH', '')
if DEBUG: print('OpenCV loader: PATH={}'.format(str(os.environ['PATH'])))
else:
# amending of LD_LIBRARY_PATH works for sub-processes only
os.environ['LD_LIBRARY_PATH'] = ':'.join(l_vars['BINARIES_PATHS']) + ':' + os.environ.get('LD_LIBRARY_PATH', '')
if DEBUG: print('OpenCV loader: replacing cv2 module')
del sys.modules['cv2']
import cv2
try:
import sys
del sys.OpenCV_LOADER
except:
pass
if DEBUG: print('OpenCV loader: DONE')
bootstrap()
如何解决这个问题?
最佳答案
最后我得到了解决方案:
#include <boost/python/numpy.hpp>
#include <boost/python/extract.hpp>
#include <boost/python.hpp>
#include <iostream>
namespace py = boost::python;
int main(int nArgCnt, char *ppArgs[]) {
Py_Initialize();
py::object pySys = py::import("sys");
auto pySysPaths = py::extract<py::list>(pySys.attr("path"))();
//Important! Add an empty path to the head of searching paths
pySysPaths.insert<std::string>(0, "");
py::object pyCv2 = py::import("cv2");
return 0;
}
解释
如果你使用命令python some_script.py
,模块的搜索路径列表已经被修改:一个空的路径字符串将被插入到列表的头部:
['', '/usr/local/lib/python3.6/dist-packages', blah, blah, blah, ...]
可以找到OpenCV的__init__.py
的第67、68行:
for p in reversed(l_vars['PYTHON_EXTENSIONS_PATHS']):
sys.path.insert(1, p)
然后 OpenCV 库的路径 (cv2.cpython-36m-x86_64-linux-gnu.so
) 被正确地插入到列表中。而 __init__.py
第 79 行的 import cv2
只是直接加载了 cv2.cpython-36m-x86_64-linux-gnu.so
文件,到目前为止,一切都适用于另一条搜索路径。
但是在cpp calling中就不一样了。没有python
程序,没有人将空的搜索路径添加到sys.path
的头部,所以__init__.py
生成了一个不应有的搜索列表路径:
['/usr/local/lib/python3.6/dist-packages', '/usr/local/lib/python3.6/dist-packages/cv2/python-3.6', '/home/devymex/3rdparty/caffe/python', blah, blah, blah, ...]
注意 /usr/local/lib/python3.6/dist-packages/cv2/python-3.6/cv2.cpython-36m-x86_64-linux-gnu.so 的真实位置
是其次,所以 __init__.py
中的第 79 行进入了 __init__.py
的递归调用,而不是加载 cv2.cpython-36m-x86_64-linux -gnu.so
这就是整个故事。
关于python - 在 boost::python::import ("cv2"上得到异常 boost::python::error_already_set ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56931058/
我需要在问题之前提供一些背景信息。请多多包涵。我使用 boost::python 向 Python 公开了一些异常类型,比如 MyExceptionType。我有一个 boomTest,我将其暴露给
我在调用 boost::python::import("cv2") 时抛出了异常 boost::python::error_already_set 首先,我写了一个python脚本pymod.py:
我一直在做一个项目,我想删除 boost 依赖项并将其替换为 Python C API。 我花了一些时间了解 Python C API,然后我看到了这个catch (error_already_set
我有一个 main.py,我用 C++ 加载并运行 void runscript ( std::string script ) { try { PyRun_SimpleStri
我是一名优秀的程序员,十分优秀!