如何找出 PyImportModule 导入失败的原因?

Posted

技术标签:

【中文标题】如何找出 PyImportModule 导入失败的原因?【英文标题】:How do I find out why importing failed with PyImportModule? 【发布时间】:2011-09-11 14:28:07 【问题描述】:

我在嵌入 Python (2.7.1) 的 C 应用程序中有此代码:


PyObject *user_dict;
PyObject *user_func;
PyObject *result;
PyObject *header_tuple;
PyObject *original_recipients;
PyObject *working_recipients;

if (!Py_IsInitialized())
    
    Py_Initialize();
    

if (!expy_exim_dict)
    
    PyObject *module = Py_InitModule(expy_exim_module, expy_exim_methods); /* Borrowed reference */
    Py_INCREF(module);                                 /* convert to New reference */
    expy_exim_dict = PyModule_GetDict(module);         /* Borrowed reference */
    Py_INCREF(expy_exim_dict);                         /* convert to New reference */
    

if (!expy_user_module)
    
    if (expy_path_add)
        
        PyObject *sys_module;
        PyObject *sys_dict;
        PyObject *sys_path;
        PyObject *add_value;

        sys_module = PyImport_ImportModule("sys");  /* New Reference */
        if (!sys_module)
            
            PyErr_Clear();
            *return_text = "Internal error, can't import Python sys module";
            log_write(0, LOG_REJECT, "Couldn't import Python 'sys' module");
            return PYTHON_FAILURE_RETURN;
            

        sys_dict = PyModule_GetDict(sys_module);               /* Borrowed Reference, never fails */
        sys_path = PyMapping_GetItemString(sys_dict, "path");  /* New reference */

        if (!sys_path || (!PyList_Check(sys_path)))
            
            PyErr_Clear();  /* in case sys_path was NULL, harmless otherwise */
            *return_text = "Internal error, sys.path doesn't exist or isn't a list";
            log_write(0, LOG_REJECT, "expy: Python sys.path doesn't exist or isn't a list");
            return PYTHON_FAILURE_RETURN;
            

        add_value = PyString_FromString(expy_path_add);  /* New reference */
        if (!add_value)
            
            PyErr_Clear();
            log_write(0, LOG_PANIC, "expy: Failed to create Python string from [%s]", expy_path_add);
            return PYTHON_FAILURE_RETURN;
            

        if (PyList_Append(sys_path, add_value))
            
            PyErr_Clear();
            log_write(0, LOG_PANIC, "expy: Failed to append [%s] to Python sys.path", expy_path_add);
            

        Py_DECREF(add_value);
        Py_DECREF(sys_path);
        Py_DECREF(sys_module);
        

    expy_user_module = PyImport_ImportModule(expy_scan_module);  /* New Reference */

    if (!expy_user_module)
        
        PyErr_Clear();
        /* Handle error */
        
    

当PyImport_ImportModule 失败时,它返回NULL。如何找出为什么导入失败? (例如,当导入模块时在嵌入之外找到工作)。

(代码是py-exim-localscan 的一部分,我想添加更多关于在极少数情况下发生的故障的信息)。

【问题讨论】:

另请参阅此问题:***.com/questions/1001216/… 【参考方案1】:

您可以通过查看引发的异常来执行此操作。目前您擦除异常(这就是PyErr_Clear() 所做的。)不要这样做,而是打印回溯或检查异常对象。请参阅http://docs.python.org/c-api/exceptions.html 了解如何从 C 代码中执行此操作,但通常最好的办法是让异常传播。

【讨论】:

让异常传播不会导致 C 程序崩溃吗? 这取决于 C 程序。如果没有处理异常并且您没有嵌入 Python,则 Python 将终止(在打印回溯之后)。如果没有任何处理异常并且您正在嵌入 Python,则从嵌入程序调用的最顶层函数将简单地返回错误。但是,如果某处处理异常(例如,在调用此函数并尝试导入模块的 Python 代码中),则无需崩溃。 C 代码是直接执行的,从不从 Python 调用。你能解释一下“嵌入Python”是什么意思吗?我的(非常有限的)理解是从 C 执行 Python 是嵌入(并且在 C 中编写模块并从 Python 调用它是扩展)。如果 Python 终止,我的 C 程序会不会正常,只是不能再使用 Python API? 如果 C 代码是嵌入 Python 的代码,则无法将异常传播到任何地方。你必须在那里处理它(通常通过打印回溯。)异常通常不会使 Python 处于不可用状态,除非异常是由内存损坏或解释器中的某些异常状态引起的。

以上是关于如何找出 PyImportModule 导入失败的原因?的主要内容,如果未能解决你的问题,请参考以下文章

UIKit 会导入啥,我该如何找出答案?

如何找出从哪个模块导入名称?

如何找出 ECS 运行状况检查失败的原因?

如何从 Nim 的导入失败中恢复?

如何调试 Python 导入失败

导入 pytz 失败时如何获取太平洋时区的当前时间?