【问题标题】:PyEval_CallObject and PyObject_CallObject return a null objectPyEval_CallObject 和 PyObject_CallObject 返回一个空对象
【发布时间】:2020-03-25 07:19:17
【问题描述】:

这是关于this one 的后续问题。 正如前一个问题 cmets 所指出的,我最初尝试导入模块是完全错误的,我应该这样做:

auto module = PyImport_ImportModule("Package1.Module1");

所以我这样做了:

auto module = PyImport_ImportModule("FV.F_V");

执行此操作后,现在我得到了更有意义的输出,如您所见:

module: 0000021306FF9B38
size: 30
FaceVerification: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
Image: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
Path: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
__builtins__: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
__cached__: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
__doc__: FV.F_V
__file__: C:\Users\Master\Anaconda3\Lib\site-packages\FV\F_V.py
__loader__: FV
__name__: FV.F_V
__package__: FV
__spec__: FV
__warningregistry__ : C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
align_face: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
cv2: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
data_transforms: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
get_central_face_attributes: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
math: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
nn: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
np: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
os: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
pickle: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
plt: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
resnet101: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
resnet18: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
resnet50: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
scipy: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
time: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
torch: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
tqdm: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
transforms : C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc

但是,当我尝试使用模块中定义的类时(即 FaceVerification 并实例化它,它会失败。 该类似乎没问题,但是尝试实例化对象的调用返回一个空对象!: PyEval_CallObjectPyObject_CallObject 我都试过了:

auto python_class = PyDict_GetItemString(pdict, "FaceVerification");

if (PyCallable_Check(python_class)) 
{
    object = PyEval_CallObject(python_class, args);
    # or 
    //object = PyObject_CallObject(python_class, args);
    //Py_DECREF(python_class);
}
else 
{
    cout << "Cannot instantiate the Python class" << endl;
    //Py_DECREF(python_class);
    //return 1;
}

无济于事。这很奇怪,因此我在F_V.py 中添加了一个新的CONSTANT 字段并尝试查看我是否可以访问它(查看模块是否确实有效)。它实际上成功地检索了常量。但是,我注意到,在重新运行 c++ 应用程序时,现在当我打印包含 PyModule_GetDict(module) 输出的 map 时,我看到了不同的结果:

module: 000001F7E07E8C28
size: 31
CONSTANT: THIS IS A TEST. REMOVE IT
FaceVerification: THIS IS A TEST. REMOVE IT
Image: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
Path: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
__builtins__: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
__cached__: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
__doc__: FV.F_V
__file__: C:\Users\Master\Anaconda3\Lib\site-packages\FV\F_V.py
__loader__: FV
__name__: FV.F_V
__package__: FV
__spec__: FV
__warningregistry__: THIS IS A TEST. REMOVE IT
align_face: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
cv2: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
data_transforms: THIS IS A TEST. REMOVE IT
get_central_face_attributes: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
math: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
nn: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
np: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
os: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
pickle: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
plt: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
resnet101: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
resnet18: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
resnet50: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
scipy: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
time: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
torch: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
tqdm: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc
transforms: C:\Users\Master\Anaconda3\Lib\site-packages\FV\__pycache__\F_V.cpython-36.pyc

最值得注意的是应该是一个类的FaceVerification 没有显示CONSTANT 字段的值!

我在这里做错了什么?

【问题讨论】:

  • 我对您的代码进行了一些研究(并且通过上一个问题进行了更多研究)。不确定这是否有帮助,但是:PyDict_GetItemString() 返回一个借来的参考。因此,Py_DECREF(python_class); 在我看来非常可疑。
  • @Scheff 谢谢,但是使用它的 sn-p 没有执行(它是从其他代码中借来的,我忘了评论那部分)。我查看了那个链接,它似乎使用了我也使用过的PyObject_CallObject。这也返回一个空对象。
  • 我同意PyObject_CallObject()。我也不知道什么会被破坏。在我们的代码中(Python 的 C++ 扩展,在我们的 C++ 应用程序中又被用作“宏引擎”),我直接调用“构造函数”函数并且从未遇到过这样的问题。如果构造函数在您的情况下失败怎么办。 (抛出的异常通常在 Python C 代码中通过返回 NULL 来表示。)如果我遇到你的情况,我会尝试使用更简单的 MCVE。 (像这样:SO: How to list all function names of a Python module in C++?。);-)
  • 非常感谢。我会看看它。非常感谢您的帮助

标签: python c++ python-embedding


【解决方案1】:

事实证明(非常感谢@Scheff),对象之所以为null,是因为构造函数内部发生了异常,因此导致对象为空。 异常的原因是路径格式错误和有问题(错误)的参数。
基本上我已经设置了这样的参数:

auto model_name = "r189";
auto model_checkpoint_path = PyUnicode_DecodeFSDefault("L:\\test_procs\\trained_models\BEST_checkpoint_r189.tar");
auto align_fn = Py_None;
auto img_bank_folder_root = PyUnicode_DecodeFSDefault("L:\\test_procs\\data\\facebank_2");
auto cache_folder = Py_None;
auto postfix = Py_None;
auto rebuild_cache = Py_False;
auto use_jit = Py_False;
auto threshold = 65; 
auto device = "cpu";

和这样的论点:

auto args = Py_BuildValue("sOOOOONNiN", model_name, model_checkpoint_path, align_fn,
                                  img_bank_folder_root, cache_folder, postfix, 
                                  rebuild_cache, use_jit, threshold, device);

这是错误的。 我把它们改成了这样:

auto model_name = "r189";
auto model_checkpoint_path = "L:\\test_procs\\trained_models\BEST_checkpoint_r189.tar";
auto align_fn = "";
auto img_bank_folder_root = "L:\\test_procs\\data\\facebank_2";
auto cache_folder = "";
auto postfix = "";
auto rebuild_cache = 0;
auto use_jit = 0;
auto threshold = 65; 
auto device = "cpu";

并像这样简化参数:

auto args = Py_BuildValue("ssssssiiis", model_name, model_checkpoint_path, align_fn,
                          img_bank_folder_root, cache_folder, postfix, 
                          rebuild_cache, use_jit, threshold, device);

完成所有这些之后,我仍然遇到异常并发现: model_checkpoint_path 需要一个固定的,因为它的路径中缺少一个 \

auto model_checkpoint_path = "L:\\test_procs\\trained_models\BEST_checkpoint_r189.tar";  

修复它:

auto model_checkpoint_path = "L:\\test_procs\\trained_models\\BEST_checkpoint_r189.tar";

从而解决了所有问题。

【讨论】:

    猜你喜欢
    • 2021-03-31
    • 2014-07-15
    • 2018-08-25
    • 2020-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多