OVH Cloud OVH Cloud

Statut de print

11 réponses
Avatar
Pierre Maurette
Bonsoir,

J'ai un programme farci de print, que je dois maintenant conditionner à
un niveau de "verbosity". Je n'ai pas de souci de performance. En
revanche, si j'ajoute des if directement, on ne voit plus que ça dans
le code.
Je pensais par exemple écrire plusieurs fonctions affiche1, ...,
afficheN. Ou une seule affiche(niveau, ???). J'aimerais ne pas modifier
ce qui est derrière le print, et qui peut être assez compliqué. Je
pensais que ce serait simple, mais je coince.
Je signale que j'ai conscience qu'en tant que débutant, je raisonne un
peu trop "à la C". Dans cette optique, une macro conviendrait
peut-être, mais je n'ai rien vu comme ça dans mes docs.
Quelqu'un aurait une idée ?

Bonne soirée...

--
Pierre Maurette

1 réponse

1 2
Avatar
Laurent Pointal
Philippe Bouige wrote:

In article <4601981d$0$27385$, Laurent Pointal
wrote:

pour Java et C++, et j'ai fait des modules de trace à moi qui identifient
très rapidement s'il faut ou non procédre le log -


Super et c'est dispo en téléchargement quelque part sur le web ?

Codialement Philippe


C'est dans pyexptools, module logger.py - mais il n'est pas long - cf
ci-dessous (coup de chance, celui-ci n'utilise pas les autres modules de
PyExp).

L'idée c'est d'avoir
* des sources de log, identifiées par des chaines
* des catégories de logs, auxquelles correspondent des masques de bits.

Généralement on n'est pas tout le temps en train de modifier les conditions
de logs, alors je préfère un système qui, quand il veut un réglage sur le
filtrage, va parcourir une arborescence et positionner ce qu'il faut pour
une décision immédiate à partir de la source et de la catégorie, plutôt
qu'un système qui à chaque log va parcourrir cette arborescence pour savoir
si le log est nécessaire.

Résultat: pour le filtrage, un simple dico qui indexe des masques de logs
par source et un test bit sur ces masques.
Initialement j'avais mon propre formatage vers une sortie fichier, puis je
suis passé au module logging quand il est devenu standard dans Python

L'implémentation date un peu (2001), je ne le referais sûrement pas comme
ça, mais l'idée est là (et c'est facilement ré-implémentable).

A+

Laurent.
.


.
#!/bin/env python
# -*- coding: ascii -*-
"""logging interface for our tools.

File : pyexptools/logger.py
Author: Laurent POINTAL
Email :
Date : 03/12/2001
License: LGPL 2.1

-----
DESCRIPTION --------------------------------------------------------------
Simple functions to do logging to logging system.

They have implicit log priority, and they automatically add missing
informations
to the message.

Written before the new standard Python logging module exists.
Now modified to use this new logging module for output.
"""

# -----
LICENSE ----------------------------------------------------------------
# pyexp - Python for Scientific Experiments Control
# Copyright (C) 2001-2002-2003 CNRS/CEA/MEN - LURE
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# ------------------------------------------------------------------------------

TODO="""
TODO: better integration with logging module.
TODO: put initialization phase of log file in a function and call it
from pyexp initialization (so that the logger module remain
independant).
"""

__revision__ = "$Id: logger.py,v 1.6 2005/02/16 21:30:17 pointal Exp $"

#============================================================================== __all__ = [ "logthis","logcritical", "logerror", "logwarning",
"logconfig", "logvalues",
"logio", "logdevlib", "logdebug", "logdebuginout", "logdebugdump",
"enablelog", "disablelog",
"registerlogsource", "registeredlogsources",
"logcategories", "catchmsg", "catchtraceback" ]

import logging
import logging.handlers
import time
import string
import threading
import types
import sys
import os
import traceback
from math import floor


#============================================================================== # Constants.
# We define our own log categories, not in term of contiguous int levels as
# syslog, but in term of bitfield.
# Note: if you need this information for a GUI, you may better get the
defined
# values in gcatconstants, and find their names in gcatnames.
LOGCRITICAL = 0x0001 # A critical situation, may result in data loss
or
# experiment stop.
LOGERROR = 0x0002 # An error important enough to stop a processing
# (raising an exception).
LOGWARNING = 0x0004 # A problem which has been detected but has no
# effect (corrected...).
LOGCONFIG = 0x0010 # Indication of configuration data.
LOGVALUES = 0x0020 # Show modification of important values.
LOGIO = 0x0100 # Trace input/output operations with devices.
LOGDEVLIB = 0x0200 # Show calls to device management libraries.
LOGDEBUG = 0x1000 # Important debug information.
LOGDEBUGINOUT = 0x2000 # Indication of function enter/exit.
LOGDEBUGDUMP = 0x4000 # Dump of deep data for debugging.
LOGALL = 0x7337 # All bits mask.


#============================================================================== # Globals.
# Accurate time measurement.
gbasetime = time.time()
gbaseclock = time.clock()
# Current default priority level.
gdefaultcats = LOGCRITICAL | LOGERROR | LOGWARNING
# Category names.
gcatnames = {
LOGCRITICAL : "CRITICAL",
LOGERROR : "ERROR",
LOGWARNING : "WARNING",
LOGCONFIG : "CONFIG",
LOGVALUES : "VALUES",
LOGIO : "IO",
LOGDEVLIB : "DEVLIB",
LOGDEBUG : "DEBUG",
LOGDEBUGINOUT : "DEBUGINOUT",
LOGDEBUGDUMP : "DEBUGDUMP"
}
# Defined categories bits (values).
gcatconstants = gcatnames.keys()
gcatconstants.sort()
# Categories for referenced sources.
gsourcecats = {}
# Python logging module corresponding loggers.
logging_loggers = {}
# Pyexp root logger, set to pass all as we do our own filtering.
pyexp_rootlogger = logging.getLogger("pyexp")
pyexp_rootlogger.setLevel(logging.DEBUG)
# to debug this module.
DEBUG = 1

#============================================================================== def logthis(source,category,fctname,format,*args) :
"""generic log with category as parameter."""
dolog (source,category,fctname,format,args)

#============================================================================== def logcritical (source,fctname,format,*args) :
"""log of important error which may result in data loose or experiment
stop.
"""
dolog (source,LOGCRITICAL,fctname,format,args)

#============================================================================== def logerror (source,fctname,format,*args) :
"""log of an error important enough to stop a processing.

Generally used when raising an exception.
"""
dolog (source,LOGERROR,fctname,format,args)

#============================================================================== def logwarning (source,fctname,format,*args) :
"""log of a problem, execution continued."""
dolog (source,LOGWARNING,fctname,format,args)

#============================================================================== def logconfig (source,fctname,format,*args) :
"""log of configuration data (read from conf source, modified...)."""
dolog (source,LOGCONFIG,fctname,format,args)

#============================================================================== def logvalues (source,fctname,format,*args) :
"""log of important values modification.

Ex. in pyexp physical element values modifications.
"""
dolog (source,LOGVALUES,fctname,format,args)

#============================================================================== def logio (source,fctname,format,*args) :
"""log of communications with devices."""
dolog (source,LOGIO,fctname,format,args)

#============================================================================== def logdevlib (source,fctname,format,*args) :
"""log of call to device management libraries."""
dolog (source,LOGDEVLIB,fctname,format,args)

#============================================================================== def logdebug (source,fctname,format,*args) :
"""log for debugging purpose."""
dolog (source,LOGDEBUG,fctname,format,args)

#============================================================================== def logdebuginout (source,fctname,format,*args) :
"""log of functions/methods entry/exit, for debugging purpose."""
dolog (source,LOGDEBUGINOUT,fctname,format,args)

#============================================================================== def logdebugdump (source,fctname,format,*args) :
"""log of deep data, for debugging purpose."""
dolog (source,LOGDEBUGDUMP,fctname,format,args)

#============================================================================== def enablelog (category,source="*",enable=1) :
"""enable/disable level of logs for a log source.

To modify all log sources, you can use "*" as source name.
To modify general default, you can use None as source name.
"""
global gsourcecats,gdefaultcats

if not enable :
category &= ~(LOGCRITICAL | LOGERROR) # Cant disable these logs.

if source in [None,"*"] :
if enable :
gdefaultcats |= category
else :
gdefaultcats&= ~category
if source == "*" :
for skey in gsourcecats.keys() :
if enable :
gsourcecats[skey] |= category
else :
gsourcecats[skey]&= ~category
elif source is not None and gsourcecats.has_key (str(source)):
if enable :
gsourcecats[str(source)] |= category
else :
gsourcecats[str(source)]&= ~category
else :
logwarning ("logger","enablelog","Source %s not referenced.",
str(source))


#============================================================================== def disablelog (category,source="*") :
"""disable level of logs for a log source.

To modify all log sources, you can use "*" as source name.
To modify general default, you can use None as source name.
"""
enablelog (category,source,0)


#============================================================================== def registerlogsource (source) :
"""create an entry in the log sources dictionary.

The source get the default level associated to it.
This method is here to allow sources to be referenced when they are
created,
this allow to have a liste of all registered sources, and to manipulate
them
later in dialogs.
"""
global gsourcecats,gdefaultcats
assert (isinstance(source,basestring))
if not gsourcecats.has_key (source) :
gsourcecats[source] = gdefaultcats
sourcelogger = logging.getLogger ("pyexp."+str(source))
sourcelogger.setLevel(logging.NOTSET) # Process by parent logger.
logging_loggers[str(source)] = sourcelogger

#============================================================================== def registeredlogsources () :
"""return list of registered log sources.

To access their log levels, use loglevel function.
"""
global gsourcecats
return gsourcecats.keys ()

#============================================================================== def logcategories (source=None) :
"""get current log categories for a source.

To get current default log level, dont give source information.
If the source is not registered, current default log level is returned
too.
"""
global gsourcecats,gdefaultcats
return gsourcecats.get (source,gdefaultcats)

#=============================================================================== def dolog (source,category,fctname,format,args) :
"""build the log string and send it to logging system.

As standard syslog output already contains date and time, hostname and
application name, we automatically insert other data at the beginning
of the message (priority indicator, thread, source...).
"""
# Filter the log.
reflevel = gsourcecats.get (source,gdefaultcats)
if not reflevel & category : return

# Get name/key of source
if source is not None :
ssource = " ["+str(source)+"]"
logging_logger = logging_loggers.get(str(source))
else :
ssource = ""
logging_logger = None

# Get name/key of function.
if fctname is not None :
sfctname = " <"+str(fctname)+">"
else :
sfctname = ""

# Find syslog priotity corresponding to our topmost level.
if category & LOGCRITICAL : loggingprio = logging.CRITICAL
elif category & LOGERROR : loggingprio = logging.ERROR
elif category & LOGWARNING : loggingprio = logging.WARNING
elif category & LOGCONFIG : loggingprio = logging.INFO
elif category & LOGVALUES : loggingprio = logging.INFO
elif category & LOGIO : loggingprio = logging.INFO
elif category & LOGDEVLIB : loggingprio = logging.INFO
elif category & LOGDEBUG : loggingprio = logging.DEBUG
elif category & LOGDEBUGINOUT : loggingprio = logging.DEBUG
elif category & LOGDEBUGDUMP : loggingprio = logging.DEBUG
else : loggingprio = logging.DEBUG

# Build time header.
timehead = "("+("%05.1f"%(((thetime()*10000)%600000)/10.0))[-7:]+"ms)"

# Get thread header.
threadhead = "<"+threading.currentThread().getName()+">"

# Build level header.
cathead = []
for cval in gcatconstants :
if category & cval :
if gcatnames.has_key(cval) :
cathead.append (gcatnames[cval])
else :
cathead.append ("0x%04X"%cval)
cathead = string.join (cathead, "+")

if len(args) == 0 :
message = format
else :
try :
if len(args)==1 and type(args[0])==types.DictType :
message = format%(args[0])
else :
message = format%args
except :
message = "Error formating "%s" with args %s"%
(str(format),str(args))

# Build full string and send it to log system.
slog = "%(timehead)s %(cathead)-10s %(threadhead)s%(ssource)s"
"%(sfctname)s: %(message)s"%locals()

# TODO: make slog logged by logging system with right fields
# from the system.
try :
if logging_logger is not None :
logging_logger.log(loggingprio, "%s",slog)
else :
pyexp_rootlogger.log(loggingprio, "%s",slog)
except Exception,e :
print >> sys.stderr, "Error while logging.",slog
print >> sys.stderr, e


#============================================================================== def thetime () :
"""return absolute current time, with clock() accuracy for Win32."""
global gbaseclock, gbasetime
if sys.platform == "win32" :
return time.clock()-gbaseclock+gbasetime
else :
return time.time()


#============================================================================== def thetimestr (t=None) :
"""format time with 1E-4 sec precision."""
if t is None : t = thetime()
s = time.strftime ("%Y-%m-%d %H:%M:%S", time.localtime (t))
s += ".%04d"%int(10000*(t-floor(t)))
return s

#============================================================================== def catchmsg () :
"""return string corresponding to **current** exception.

Function to use in catch handlers, to give to log functions the
exception
string.
"""
e = sys.exc_info () # (type, value, traceback).
lines = traceback.format_exception_only(e[0], e[1])
return string.join (lines)

#============================================================================== def catchtraceback (e=None) :
"""return string corresponding to **current** exception traceback.

Function to use in catch handlers, give to log function full exception
traceback.
"""
if e is None :
e = sys.exc_info () # (type, value, traceback).
lines = traceback.format_exception(e[0], e[1], e[2])
return string.join (lines)


#============================================================================== # Just to intialize stuff.
# Get the first clock.
thetime ()
# Set logging to log all we send to it (we implement a different filter
# system in this module - may try to have more integration with standard
# logging module later).
# We send these logs to a temporary file.
logfilename = os.getenv("PYEXP_LOGFILE")
if not logfilename :
tmpdir = os.getenv("TMP")
if not tmpdir :
tmpdir = os.getenv("TEMP")
if tmpdir :
logfilename = os.path.join(tmpdir,"pyexp.log")
else : # Use current working directory
logfilename = os.path.abspath("pyexp.log")
try :
# We log to a text file with a rotating system to keep a maximum of
# six 1MB files.
hdlr logging.handlers.RotatingFileHandler(logfilename,maxBytes24*1024,backupCount=5)
formatter = logging.Formatter('%(asctime)s %(message)s')
hdlr.setFormatter(formatter)
pyexp_rootlogger.addHandler(hdlr)
except Exception,e :
print >> sys.stderr, "Error while setting base log file.",logfilename
print >> sys.stderr, e

# Set default log level for unclassified logs here.
enablelog (LOGCRITICAL | LOGERROR | LOGWARNING)


1 2