[Python-checkins] r80396 - in python/trunk: Doc/library/syslog.rst Misc/NEWS Modules/syslogmodule.c

sean.reifschneider python-checkins at python.org
Fri Apr 23 10:31:55 CEST 2010


Author: sean.reifschneider
Date: Fri Apr 23 10:31:55 2010
New Revision: 80396

Log:
issue8451: Making syslog module use sys.argv[0] for "ident".


Modified:
   python/trunk/Doc/library/syslog.rst
   python/trunk/Misc/NEWS
   python/trunk/Modules/syslogmodule.c

Modified: python/trunk/Doc/library/syslog.rst
==============================================================================
--- python/trunk/Doc/library/syslog.rst	(original)
+++ python/trunk/Doc/library/syslog.rst	Fri Apr 23 10:31:55 2010
@@ -11,42 +11,66 @@
 Refer to the Unix manual pages for a detailed description of the ``syslog``
 facility.
 
+This module wraps the system ``syslog`` module.  A pure Python
+library that can speak to a syslog server is available in
+the :mod:`logging.handlers` module as :class:`SysLogHandler`.
+
 The module defines the following functions:
 
 
 .. function:: syslog([priority,] message)
 
-   Send the string *message* to the system logger.  A trailing newline is added if
-   necessary.  Each message is tagged with a priority composed of a *facility* and
-   a *level*.  The optional *priority* argument, which defaults to
-   :const:`LOG_INFO`, determines the message priority.  If the facility is not
-   encoded in *priority* using logical-or (``LOG_INFO | LOG_USER``), the value
-   given in the :func:`openlog` call is used.
-
-
-.. function:: openlog(ident[, logopt[, facility]])
-
-   Logging options other than the defaults can be set by explicitly opening the log
-   file with :func:`openlog` prior to calling :func:`syslog`.  The defaults are
-   (usually) *ident* = ``'syslog'``, *logopt* = ``0``, *facility* =
-   :const:`LOG_USER`.  The *ident* argument is a string which is prepended to every
-   message.  The optional *logopt* argument is a bit field - see below for possible
-   values to combine.  The optional *facility* argument sets the default facility
-   for messages which do not have a facility explicitly encoded.
+   Send the string *message* to the system logger.  A trailing newline is
+   added if necessary.  Each message is tagged with a priority composed
+   of a *facility* and a *level*.  The optional *priority* argument, which
+   defaults to :const:`LOG_INFO`, determines the message priority.  If the
+   facility is not encoded in *priority* using logical-or (``LOG_INFO |
+   LOG_USER``), the value given in the :func:`openlog` call is used.
+
+   If :func:`openlog` has not been called prior to the call to
+   :func:'syslog', ``openlog()`` will be called with no arguments.
+
+
+.. function:: openlog([ident[, logopt[, facility]]])
+
+   Logging options of subsequent :func:`syslog` calls can be set by
+   calling :func:`openlog`.  :func:`syslog` will call :func:`openlog`
+   with no arguments if the log is not currently open.
+
+   The optional *ident* keyword argument is a string which is prepended
+   to every message, and defaults to ''sys.argv[0]'' with leading
+   path components stripped.  The optional *logopt* keyword argument
+   (default=0) is a bit field - see below for possible values to combine.
+   The optional *facility* keyword argument (default=:const:`LOG_USER`)
+   sets the default facility for messages which do not have a facility
+   explicitly encoded.
+
+   .. versionchanged::3.2
+      In previous versions, keyword arguments were not allowed, and *ident*
+      was required.  The default for *ident* was dependent on the system
+      libraries, and often was ''python'' instead of the name of the
+      python program file.
 
 
 .. function:: closelog()
 
-   Close the log file.
+   Reset the syslog module values and call the system library
+   ''closelog()''.
+
+   This causes the module to behave as it does when initially imported.
+   For example, :func:'openlog' will be called on the first :func:'syslog'
+   call (if :func:'openlog' hasn't already been called), and *ident*
+   and other :func:'openlog' parameters are reset to defaults.
 
 
 .. function:: setlogmask(maskpri)
 
-   Set the priority mask to *maskpri* and return the previous mask value.  Calls to
-   :func:`syslog` with a priority level not set in *maskpri* are ignored.  The
-   default is to log all priorities.  The function ``LOG_MASK(pri)`` calculates the
-   mask for the individual priority *pri*.  The function ``LOG_UPTO(pri)``
-   calculates the mask for all priorities up to and including *pri*.
+   Set the priority mask to *maskpri* and return the previous mask value.
+   Calls to :func:`syslog` with a priority level not set in *maskpri*
+   are ignored.  The default is to log all priorities.  The function
+   ``LOG_MASK(pri)`` calculates the mask for the individual priority
+   *pri*.  The function ``LOG_UPTO(pri)`` calculates the mask for all
+   priorities up to and including *pri*.
 
 The module defines the following constants:
 
@@ -64,3 +88,24 @@
    :const:`LOG_PID`, :const:`LOG_CONS`, :const:`LOG_NDELAY`, :const:`LOG_NOWAIT`
    and :const:`LOG_PERROR` if defined in ``<syslog.h>``.
 
+
+Examples
+--------
+
+Simple example
+~~~~~~~~~~~~~~
+
+A simple set of examples::
+
+   import syslog
+
+   syslog.syslog('Processing started')
+   if error:
+      syslog.syslog(syslog.LOG_ERR, 'Processing started')
+
+An example of setting some log options, these would include the process ID
+in logged messages, and write the messages to the destination facility
+used for mail logging::
+
+   syslog.openlog(logopt=syslog.LOG_PID, facility=syslog.LOG_MAIL)
+   syslog.syslog('E-mail processing initiated...')

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Fri Apr 23 10:31:55 2010
@@ -25,6 +25,10 @@
 Library
 -------
 
+- Issue #8451: Syslog module now uses basename(sys.argv[0]) instead of
+  the string "python" as the *ident*.  openlog() arguments are all optional
+  and keywords.
+
 - Issue #8108: Fix the unwrap() method of SSL objects when the socket has
   a non-infinite timeout.  Also make that method friendlier with applications
   wanting to continue using the socket in clear-text mode, by disabling

Modified: python/trunk/Modules/syslogmodule.c
==============================================================================
--- python/trunk/Modules/syslogmodule.c	(original)
+++ python/trunk/Modules/syslogmodule.c	Fri Apr 23 10:31:55 2010
@@ -26,6 +26,11 @@
 
 Revision history:
 
+2010/04/20 (Sean Reifschneider)
+  - Use basename(sys.argv[0]) for the default "ident".
+  - Arguments to openlog() are now keyword args and are all optional.
+  - syslog() calls openlog() if it hasn't already been called.
+
 1998/04/28 (Sean Reifschneider)
   - When facility not specified to syslog() method, use default from openlog()
     (This is how it was claimed to work in the documentation)
@@ -45,6 +50,7 @@
 /* syslog module */
 
 #include "Python.h"
+#include "osdefs.h"
 
 #include <syslog.h>
 
@@ -52,26 +58,80 @@
 static PyObject *S_ident_o = NULL;			/*  identifier, held by openlog()  */
 
 
+static PyObject *
+syslog_get_argv(void)
+{
+	/* Figure out what to use for as the program "ident" for openlog().
+	 * This swallows exceptions and continues rather than failing out,
+	 * because the syslog module can still be used because openlog(3)
+	 * is optional.
+	 */
+
+	Py_ssize_t argv_len;
+	PyObject *scriptobj;
+	char *atslash;
+	PyObject *argv = PySys_GetObject("argv");
+
+	if (argv == NULL) {
+		return(NULL);
+	}
+
+	argv_len = PyList_Size(argv);
+	if (argv_len == -1) {
+		PyErr_Clear();
+		return(NULL);
+	}
+	if (argv_len == 0) {
+		return(NULL);
+	}
+
+	scriptobj = PyList_GetItem(argv, 0);
+	if (!PyString_Check(scriptobj)) {
+		return(NULL);
+	}
+	if (PyString_GET_SIZE(scriptobj) == 0) {
+		return(NULL);
+	}
+
+	atslash = strrchr(PyString_AsString(scriptobj), SEP);
+	if (atslash) {
+		return(PyString_FromString(atslash + 1));
+	} else {
+		Py_INCREF(scriptobj);
+		return(scriptobj);
+	}
+
+	return(NULL);
+}
+
+
 static PyObject * 
-syslog_openlog(PyObject * self, PyObject * args)
+syslog_openlog(PyObject * self, PyObject * args, PyObject *kwds)
 {
 	long logopt = 0;
 	long facility = LOG_USER;
-	PyObject *new_S_ident_o;
+	PyObject *new_S_ident_o = NULL;
+	static char *keywords[] = {"ident", "logoption", "facility", 0};
 
-	if (!PyArg_ParseTuple(args,
-			      "S|ll;ident string [, logoption [, facility]]",
-			      &new_S_ident_o, &logopt, &facility))
+	if (!PyArg_ParseTupleAndKeywords(args, kwds,
+			      "|Sll:openlog", keywords, &new_S_ident_o, &logopt, &facility))
 		return NULL;
 
-	/* This is needed because openlog() does NOT make a copy
-	 * and syslog() later uses it.. cannot trash it.
-	 */
+	if (new_S_ident_o) { Py_INCREF(new_S_ident_o); }
+
+	/*  get either sys.argv[0] or use "python" otherwise  */
+	if (!new_S_ident_o) {
+		new_S_ident_o = syslog_get_argv();
+		}
+
 	Py_XDECREF(S_ident_o);
 	S_ident_o = new_S_ident_o;
-	Py_INCREF(S_ident_o);
 
-	openlog(PyString_AsString(S_ident_o), logopt, facility);
+	/* At this point, S_ident_o should be INCREF()ed.  openlog(3) does not
+	 * make a copy, and syslog(3) later uses it.  We can't garbagecollect it
+	 */
+
+	openlog(S_ident_o ? PyString_AsString(S_ident_o) : NULL, logopt, facility);
 
 	Py_INCREF(Py_None);
 	return Py_None;
@@ -92,6 +152,21 @@
 			return NULL;
 	}
 
+	/*  call openlog if no current identifier  */
+	if (!S_ident_o) {
+		PyObject *openargs;
+
+		/* Continue even if PyTuple_New fails, because openlog(3) is optional.
+		 * So, we can still do loggin in the unlikely event things are so hosed
+		 * that we can't do this tuple.
+		 */
+		if ((openargs = PyTuple_New(0))) {
+			PyObject *openlog_ret = syslog_openlog(self, openargs, NULL);
+			Py_XDECREF(openlog_ret);
+			Py_DECREF(openargs);
+		}
+	}
+
 	Py_BEGIN_ALLOW_THREADS;
 	syslog(priority, "%s", message);
 	Py_END_ALLOW_THREADS;
@@ -145,7 +220,7 @@
 /* List of functions defined in the module */
 
 static PyMethodDef syslog_methods[] = {
-	{"openlog",	syslog_openlog,		METH_VARARGS},
+	{"openlog",	(PyCFunction) syslog_openlog,		METH_VARARGS | METH_KEYWORDS},
 	{"closelog",	syslog_closelog,	METH_NOARGS},
 	{"syslog",	syslog_syslog,		METH_VARARGS},
 	{"setlogmask",	syslog_setlogmask,	METH_VARARGS},


More information about the Python-checkins mailing list