在C中使用Python logging模块

3
我希望在C程序中使用Python日志模块。我已经阅读了http://docs.python.org/2/extending/embedding.html上的文档,但是我卡住了。
这是我想要实现的(Python等效):
import logging, logging.handlers
logger = logging.getLogger('')
logger.setLevel(logging.DEBUG)
socketHandler = logging.handlers.SocketHandler('localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT)
logger.addHandler(socketHandler)
logger.debug("whats up, doc?")

这是我在C语言中尝试的内容:
PyObject *logging, *get_logger, *pValue, *set_level, *strargs;
*logging = PyImport_ImportModule("logging")
*get_logger = PyObject_GetAttrString(logging, "getLogger")
*pValue = PyObject_CallObject(get_logger, NULL)
*set_level = PyObject_GetAttrString(logging, "setLevel")
*strargs = PyString_FromString("logging.DEBUG")
pValue = PyObject_CallObject(set_level, strargs);

我不确定如何创建socketHandler。有什么提示吗?谢谢!


您最终想要实现什么目标?如果您正在为Python编写一个C库,那么库不应设置记录器,这应该由主程序完成。如果您正在编写嵌入Python的C程序,您仍然可以通过eval一些Python代码来处理设置,而不是在C中完成整个设置过程。 - millimoose
我正在编写一个嵌入Python的C程序。在我的初始迭代中,我尝试使用PyRun_SimpleString(...),但据我所知,我无法传递参数。因此,如果我想要在SimpleString中调用logger.debug,并将参数传递进去,就必须将其硬编码进去。 - user2406467
有一堆 PyRun_X 函数,其中一些允许您将值传递到上下文中。但是您可能不需要这些函数,因为如果我正确理解文档的话,那么您就无法再使用解释器进行设置了。另外,您需要哪些参数来设置记录器?(通过“设置”我指的是“最后一个 logger.debug(...) 调用之前的所有内容”) - millimoose
以下是我的 Python 代码片段中的参数:我需要附加一个 SocketHandler 并设置记录器级别。 - user2406467
好的,但是你的Python代码片段中有很多值不清楚是不能硬编码还是不能从Python代码中读取配置文件。 - millimoose
logger.debug(...) 命令之前的所有内容都可以是硬编码或从配置文件中读取的。它们在我的程序运行过程中不会改变。 - user2406467
1个回答

1
在Python C API中,就像在Python中一样,“创建对象”只是调用其类型。
不幸的是,在C中做所有的getattr工作真的很烦人。根据你想从C中做什么,你可以提供一堆辅助模块,将它们在导入时传递给C(例如,请参见https://github.com/couchbase/couchbase-python-client/blob/master/couchbase/_bootstrap.py)。
无论如何,Python是一种非常简单的语言,内外部都是如此。因此,让我们把它分解开来。
socketHandler = logging.handlers.SocketHandler('localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT)

PEP-7指的是C89,但更容易在C99中展示:

PyObject *logging = PyImport_ImportModule("logging");
PyObject *handlers = PyObject_GetAttrString(logging, "handlers");

现在,构建套接字处理程序。从C API调用某些东西可以使用PyObject_CallObject完成,它适用于任何定义了__call__的内容。但首先,您需要构建参数...
PyObject *sh_ctor = PyObject_GetAttrString(handlers, "SocketHandler");
PyObject *args = Py_BuildValue("(si)", "localhost", DEFAULT_LOGGING_PORT)
PyObject *sh_instance = PyObject_CallObject(sh_ctor, args);

我不会在这里展示如何构建参数,甚至不会进行适当的错误检查或引用计数。请注意,在C API中,如果函数失败,则返回NULL并引发异常(除非另有说明)。

实际上,我建议您确定您实际需要从C中使用多少logging模块,并将该功能包装在一个更简单的子集中,您可以从C中调用该子集。请参阅我上面链接到的_bootstrap.py模块。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接