Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

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

10 réponses

1 2
Avatar
Laurent Pointal
Pierre Maurette wrote:

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 ?



Idées en vrac:
* regarder du côté du module logging [*] qui est fait pour ça.Ca va
t'obliger à revoir ce qui est derrière le print...

* afficheN ou affiche(n,...) comme tu proposes, avec utilisation de *args
pour récupérer les éléments que tu séparais précédement par des virgules
dans le print, pour éviter de trop casser ton code.

* print >>fn, ... avec des fN qui sont des objets implémentant la méthode
write, réalisant le filtrage en fonction du niveau de verbosité, et
effectuant le log lorsque nécessaire (typiquement sur retour à la ligne).
Ca pose un (AMA gros) problème d'efficacité car print va dans tous les cas
formater la chaîne avant d'appeler write().

Bon courage.

A+

Laurent.



[*] Note: perso je trouve que logging est un peu usine à gaz et pas assez
efficace au niveau temps de traitement pour savoir si un log doit ou non
être généré. Ils ont peut être un peu trop voulu copier sur ce qui existe
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 - dans certains softs on
peut en générer une quantité monstre et il ne faut pas perdre trop de temps
là dessus.

Avatar
pbouige
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

Avatar
Bruno Desthuilliers
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.


Quelque chose comme ça ?

def myprint(level, *args):
if level >= log_level:
print >> sys.stderr, " ".join(map(str,args))


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.


Ya pas. Dieu merci.

Quelqu'un aurait une idée ?


Si ton programme est un tant soit peu sérieux:

http://docs.python.org/lib/module-logging.html

Ca te donnera peut-être un peu plus de travail à mettre en place pour
commencer, mais au moins ce sera propre une bonne fois pour toutes.

Avatar
Pierre Maurette
[...]
Idées en vrac:


Merci pour vos suggestions. Je sais au moins que je n'étais pas passé à
coté d'une évidence.

* regarder du côté du module logging [*] qui est fait pour ça.Ca va
t'obliger à revoir ce qui est derrière le print...


J'avais laissé tomber, vu qu'il s'agit d'un petit utilitaire et que
j'avais des souvenirs de truc assez lourd, en Java. Mais je vais
peut-être y revenir.

* afficheN ou affiche(n,...) comme tu proposes, avec utilisation de *args
pour récupérer les éléments que tu séparais précédement par des virgules
dans le print, pour éviter de trop casser ton code.


Ben, ça marche. Je ne sais plus ce qui m'avait bloqué, peut-être
certaines constructions de print. Mais il faut accepter de multiplier
les appels à print, sinon ça se complique. Dans mon cas ce n'est pas un
souci:

def Affiche(self, level, *s):
if not level > self.dicodata['verbosity']:
for o in s:
print o,
print


* print >>fn, ... avec des fN qui sont des objets implémentant la méthode
write, réalisant le filtrage en fonction du niveau de verbosité, et
effectuant le log lorsque nécessaire (typiquement sur retour à la ligne).
Ca pose un (AMA gros) problème d'efficacité car print va dans tous les cas
formater la chaîne avant d'appeler write().


C'est peut-être pas mal, je n'ai pas de souci d'efficacité dans un
contexte de transferts FTP. Je n'avais pas trouvé de doc qui m'explique
ce que pouvait être fn à part un objet file. J'avais également regardé
du coté de __str__, ainsi que de l'affichage différé en filtrant un log
maximum. Mais j'arrive à des trucs trop compliqués.

Bon, il faut que je remette tout ça au propre. Le machin, c'est une
petite classe que j'utilise soit en ligne de commande, soit par
l'intermédiaire d'un petit cliquodrome en Tkinter. Dans ce second cas,
je redirige déjà le print vers un tempfile que je récupère dans le
cliquodrome. Mais là j'ai déjà fait une erreur de conception en
intégrant la redirection trop tard. Résultat, il me faut revoir le
traitement des erreurs pour toujours au moins afficher le log. Donc
lire tranquillement les doc sur try...except...finally et regarder
peut-être du coté du module logging.

Bon courage.


Merci, et bonne journée...

--
Pierre Maurette

Avatar
Pierre Maurette

[...]

Quelque chose comme ça ?

def myprint(level, *args):
if level >= log_level:
print >> sys.stderr, " ".join(map(str,args))


Merci, j'ai corrigé mon code (voir autre réponse de 11:18:21) ainsi:

def Affiche(self, level, *s):
if not level > self.dicodata['verbosity']:
print "".join(map(str,s))

[...]

Si ton programme est un tant soit peu sérieux:


C'est à dire ?

--
Pierre Maurette

Avatar
Bruno Desthuilliers

[...]

Quelque chose comme ça ?

def myprint(level, *args):
if level >= log_level:
print >> sys.stderr, " ".join(map(str,args))


Merci, j'ai corrigé mon code (voir autre réponse de 11:18:21) ainsi:

def Affiche(self, level, *s):


pep08 :
def affiche(self, level, *s):

if not level > self.dicodata['verbosity']:


La négation n'arrange pas la lisibilité. KISS:
if level < self.self.dicodata['verbosity']:

print "".join(map(str,s))


la sortie standard est pour les résultats du programme (de façon à
pouvoir chainer plusieurs programmes). Les messages d'erreur et
assimilés doivent aller vers la sortie d'erreur (aka sys.stderr).

print >> sys.stderr, "".join(map(str,s))


Si tu veux pouvoir rediriger vers un fichier sans toucher à sys.stderr
ni demander explicitement une redirection, tu peux aussi définir un
attribut stderr dans ta classe, qui pointe par defaut sur sys.stderr:

import sys

class MonAppli(object):
def __init__(self, stderr=sys.stderr, ...):
self.stderr = stderr

def log(self, level, *what):
if level <= self.dicodata['verbosity']:
print >> self.stderr, "".join(map(str,s))


logfile = open('/path/to/logfile', 'w')
app = MonAppli(stderr=logfile)

[...]

Si ton programme est un tant soit peu sérieux:


C'est à dire ?



Est-ce que c'est un petit utilitaire à usage restreint (voir personnel),
ou est-ce que c'est une appli 'critique' ? Mais bon, la réponse est dans
ton autre post, je pense. Ceci étant, quitte à reprendre du code, autant
le faire au mieux, non ?


Avatar
Pierre Maurette

[...]

pep08 :


C'est quoi ? Des règles de style ?

def affiche(self, level, *s):

if not level > self.dicodata['verbosity']:


La négation n'arrange pas la lisibilité. KISS:
if level < self.self.dicodata['verbosity']:


Ce n'est pas le même chose. Et puis pour moi ici la négation améliore
la lisibilité.
C'est quoi, le 'self.self...', je ne comprends pas ?


print "".join(map(str,s))


la sortie standard est pour les résultats du programme (de façon à pouvoir
chainer plusieurs programmes). Les messages d'erreur et assimilés doivent
aller vers la sortie d'erreur (aka sys.stderr).

print >> sys.stderr, "".join(map(str,s))


Si tu veux pouvoir rediriger vers un fichier sans toucher à sys.stderr ni
demander explicitement une redirection, tu peux aussi définir un attribut
stderr dans ta classe, qui pointe par defaut sur sys.stderr:

import sys

class MonAppli(object):
def __init__(self, stderr=sys.stderr, ...):
self.stderr = stderr

def log(self, level, *what):
if level <= self.dicodata['verbosity']:
print >> self.stderr, "".join(map(str,s))


logfile = open('/path/to/logfile', 'w')
app = MonAppli(stderr=logfile)


C'est sans objet dans mon programme, et mes soucis concernent à priori
stdout. stdout et stderr sont soit la console, soit redirigés
explicitement vers le même tempfile. Il est possible que la suite me
pousse à les séparer.


[...]

Si ton programme est un tant soit peu sérieux:


C'est à dire ?



Est-ce que c'est un petit utilitaire à usage restreint (voir personnel), ou
est-ce que c'est une appli 'critique' ? Mais bon, la réponse est dans ton
autre post, je pense. Ceci étant, quitte à reprendre du code, autant le faire
au mieux, non ?


Je *tente* généralement de faire sérieusement, mais dans la joie et la
bonne humeur, ce que j'entreprends. La vaisselle, la bête-à-deux-dos,
la programmation, ma toilette, la plomberie, le caressage d'épagneul...
Bien entendu, les premiers essais ne sont jamais à la hauteur de mes
ambitions. J'admets que je perds souvent du temps à aller trop vite
puis à tout reprendre à zéro, mais je ne suis pas parfait. Il faut dire
que je suis l'aîné et que logiquement, mes frères et soeurs sont plus
réussis.

--
Pierre Maurette



Avatar
Bruno Desthuilliers

[...]

pep08 :


C'est quoi ? Des règles de style ?


Oui. Les conventions de nommage sont importantes en Python. Quand je
voie un identifiant comme Affiche, je pense immédiatement à une classe.
Je ne suis probablement pas le seul.


if not level > self.dicodata['verbosity']:


La négation n'arrange pas la lisibilité. KISS:
if level < self.self.dicodata['verbosity']:


Ce n'est pas le même chose. Et puis pour moi ici la négation améliore la
lisibilité.
C'est quoi, le 'self.self...', je ne comprends pas ?



Désolé, erreur entre la chaise et le clavier. Il fallait bien sûr lire:
if level <= self.dicodata['verbosity']:


Pour ce qui est de la lisibilité, ok, il y a une part de subjectivité.
Mais les études montrent que d'une manière générale, moins on a de
négations dans un prédicat, plus c'est facile à interpréter pour notre
pauvre petit cerveau.

Mes deux centimes...



Avatar
Pierre Maurette

[...]

pep08 :


C'est quoi ? Des règles de style ?


Oui. Les conventions de nommage sont importantes en Python. Quand je voie un
identifiant comme Affiche, je pense immédiatement à une classe. Je ne suis
probablement pas le seul.


Merci, je vais faire chauffer la refactoreuse. J'ai trouvé ça, à défaut
d'un résumé plus concis: <URL:http://www.python.org/dev/peps/pep-0008/>

--
Pierre Maurette



Avatar
Bruno Desthuilliers

[...]

pep08 :


C'est quoi ? Des règles de style ?


Oui. Les conventions de nommage sont importantes en Python. Quand je
voie un identifiant comme Affiche, je pense immédiatement à une
classe. Je ne suis probablement pas le seul.


Merci, je vais faire chauffer la refactoreuse. J'ai trouvé ça, à défaut
d'un résumé plus concis: <URL:http://www.python.org/dev/peps/pep-0008/>

C'est le bon.





1 2