473,722 Members | 2,161 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

improvements for the logging package

Hi,

while working on something in my current project I have made several
improvements to the logging package in Python, two of them are worth
mentioning:
1. addition of a logging record field %(function)s, which results in
the name
of the entity which logged the record. My version even deduces the
class name in the case which the logger is a bound method, and assuming
the name of the "self" variable is indeed "self".

This ability can be turned off, for performance reasons, and is useful
for debugging phases.

2. log coloring formatter (useful for console output) - support for log
lines like BLUE<<text>>, etc.

Now, I asked several friends of mine who program in Python often, and
they told me they could use these features very much.

I'm taking a risk here, that maybe someone already proposed this in
this group, but I'll ask either way:
Has anyone thought of posting a PEP about this? Do you think I should?

I have made a great use of the logging package, and would certainly
like to see it evolve and include more features.

Sep 5 '05 #1
23 2217
[Rotem wrote]
while working on something in my current project I have made several
improvements to the logging package in Python, two of them are worth
mentioning:
1. addition of a logging record field %(function)s, which results in
the name
of the entity which logged the record. My version even deduces the
class name in the case which the logger is a bound method, and assuming
the name of the "self" variable is indeed "self".

This ability can be turned off, for performance reasons, and is useful
for debugging phases.

2. log coloring formatter (useful for console output) - support for log
lines like BLUE<<text>>, etc.

Now, I asked several friends of mine who program in Python often, and
they told me they could use these features very much.

I'm taking a risk here, that maybe someone already proposed this in
this group, but I'll ask either way:
Has anyone thought of posting a PEP about this? Do you think I should?
Cool. Your additions sound useful.
This might be a bit small for a PEP (though I am hardly an authority).
You could post your patch on a new bug on SourceForge.

http://sourceforge.net/tracker/?group_id=5470
I have made a great use of the logging package, and would certainly
like to see it evolve and include more features.


Something to consider that would help to get the logging package more
used would be to write up your experiences with it: write a tutorial or
HOWTO or improvements of the core logging docs. Currently the logging
package looks fairly uninviting/untractable to new users.

Cheers
Trent

--
Trent Mick
Tr****@ActiveSt ate.com
Sep 6 '05 #2
while working on something in my current project I have made several
improvements to the logging package in Python, two of them are worth
mentioning:

...
Trent> Cool. Your additions sound useful.

Perhaps so, but the logging module seems like such an unpythonic beast to
me. How about cleaning it up (*) before we add more to it? Stuff like
colorizing seems like it belongs in its own module (presuming a reasonably
general markup scheme can be agreed upon) so it can be used outside the
logging package.

(*) Stuff that seems very odd to me:

- It's a package, but contrary to any other package I've ever seen, most
of its functionality is implemented in __init__.py. __init__.py is
roughly four times larger than the next largest (bsddb, which is a
beast because BerkDB has gotten so big over the years and the
module/package has strived to remain backwards-compatible).

- It's still too hard to use. The obvious 'hello world' example

import logging
logging.info('h ello world')

ought to just work (implicitly add a stream handler connected to
stderr to the root logger).

- Its functionality is partitioned in sometimes odd ways. For example,
it has a handlers module, but what I presume would be the most
commonly used handler (StreamHandler) is not defined there. It's in
(you have three guesses and the first two don't count) __init__.py
instead of in logging.handler s. Consequently, browsing in the obvious
way fails to find the StreamHandler class.

- It doesn't use PEP 8 style as far as naming is concerned, instead
doing some sort of Java or C++ or Perl camelCase thing. Eschewing PEP
8 is fine for other stuff, but code in the Python core (especially new
code like the logging module) should strive to adhere to PEP 8, since
many people will use the core code as a pattern for their own code.

Skip
Sep 7 '05 #3
[sk**@pobox.com wrote]
Perhaps so, but the logging module seems like such an unpythonic beast to
me. How about cleaning it up (*) before we add more to it?
Yes. I was also trying to encourage Rotem to get involved in other parts
of the logging module/package later on in my email. :)
Stuff like colorizing seems like it belongs in its own module
(presuming a reasonably general markup scheme can be agreed upon) so
it can be used outside the logging package.
Yah, you are probably right. Most additions to the logging system could
easily live as their own separate pieces.
(*) Stuff that seems very odd to me:

- It's a package, but contrary to any other package I've ever seen, most
of its functionality is implemented in __init__.py. __init__.py is
roughly four times larger than the next largest (bsddb, which is a
beast because BerkDB has gotten so big over the years and the
module/package has strived to remain backwards-compatible).
I'm not defending the implementation, but does this cause any particular
problems?

The obvious 'hello world' example

import logging
logging.info('h ello world')

ought to just work (implicitly add a stream handler connected to
stderr to the root logger).
Maybe. Unless that causes troubles for real use. Having lazy
configuration like this means that it can be a subtle thing for
top-level application code to setup the proper logging configuration.

I cringe a little bit when I see this presented as the "hello world"
example. My basic hello world tends to be:

import logging
log = logging.getLogg er("name-of-my-module-or-script")

# use log.{debug|info |warn|error}() in module/script...
#...

if __name__ == "__main__":
logging.basicCo nfig()
#...

and then I wish again that the default output were a bit nicer for my
most common usage -- which is logging to the command line in scripts --
rather than looking more like to web server error/access logs.

I think the usability of the logging module could be much improved with
a nicer introduction to it (i.e. docs). It's not really a "hello world"
type of tool. Its usefulness only really shows in larger use cases.

- Its functionality is partitioned in sometimes odd ways. For example,
it has a handlers module, but what I presume would be the most
commonly used handler (StreamHandler) is not defined there. It's in
(you have three guesses and the first two don't count) __init__.py
instead of in logging.handler s. Consequently, browsing in the obvious
way fails to find the StreamHandler class.

- It doesn't use PEP 8 style as far as naming is concerned, instead
doing some sort of Java or C++ or Perl camelCase thing. Eschewing PEP
8 is fine for other stuff, but code in the Python core (especially new
code like the logging module) should strive to adhere to PEP 8, since
many people will use the core code as a pattern for their own code.


Perhaps Vijay (who did all the implementation) can comment on these.
Unfortunately backwards-compat might restrict some cleanups to the
package, but perhaps not too much. I did a poor job of keeping up with
the package after I laid out an initial design, er copied an initial
design from Java's log4j package (and I'm not even a Java guy). :(

Trent

--
Trent Mick
Tr****@ActiveSt ate.com
Sep 7 '05 #4
I recommend py.log (part of the py lib) as an example of a pythonic
implementation of logging. It uses a keyword-based mechanism and it
distinguishes between "producers" of log messages (i.e. your app) and
"consumers" of log messages (i.e. stdout, stderr, a database, a mail
server, etc.)

You can do things like:
import py
py.log.default( 'hello world') [default] hello world log = py.log.Producer ("myapp")
log.info('hello again') [myapp:info] hello again log.hello('agai n')

[myapp:hello] again

See
<http://agiletesting.bl ogspot.com/2005/06/keyword-based-logging-with-py-library.html>
for more details.

Grig

Sep 7 '05 #5
- It's a package, but contrary to any other package I've ever seen,
most of its functionality is implemented in __init__.py.
Trent> I'm not defending the implementation, but does this cause any
Trent> particular problems?

No, it just seems symptomatic of some potential organizational problems.
import logging
logging.info('h ello world')

ought to just work (implicitly add a stream handler connected to
stderr to the root logger).
Trent> Maybe. Unless that causes troubles for real use.

Maybe there's a bug then (or maybe the docs still need work). When I
executed (all of these examples were typed at an interactive prompt):

import logging
logging.info('h ello world')

I get no output. Looking at the doc for the basicConfig() function, I see:

The functions debug(), info(), warning(), error() and critical() will
call basicConfig() automatically if no handlers are defined for the root
logger.

If I read that right, my "hello world" example ought to work. I tried:

import logging
logging.getLogg er("main")
logging.info("h ello world")

and

import logging
logging.basicCo nfig()
logging.info("h ello world")

and

import logging
logging.basicCo nfig()
log = logging.getLogg er("main")
log.info("hello world")

Shouldn't one of these have emitted a "hello world" to stderr? (Maybe not.
Maybe I need to explicitly add handlers to non-root loggers.)

Trent> Having lazy configuration like this means that it can be a subtle
Trent> thing for top-level application code to setup the proper logging
Trent> configuration.

Again, based on my reading of the basicConfig doc, it seems like the logging
package is supposed to already do that.

Trent> I think the usability of the logging module could be much
Trent> improved with a nicer introduction to it (i.e. docs). It's not
Trent> really a "hello world" type of tool. Its usefulness only really
Trent> shows in larger use cases.

I agree about the docs. Whatever the "hello world" example is (I clearly
haven't figured it out yet), it ought to be right at the top of the docs.

If logging isn't trivial to use, then many simple apps won't use logging.
Consequently, when they grow, logging has to be retrofitted.
- Its functionality is partitioned in sometimes odd ways. For
example, it has a handlers module, but what I presume would be the
most commonly used handler (StreamHandler) is not defined there.

- It doesn't use PEP 8 style as far as naming is concerned, instead
doing some sort of Java or C++ or Perl camelCase thing.


Trent> Perhaps Vijay (who did all the implementation) can comment on
Trent> these. Unfortunately backwards-compat might restrict some
Trent> cleanups to the package, but perhaps not too much. I did a poor
Trent> job of keeping up with the package after I laid out an initial
Trent> design, er copied an initial design from Java's log4j package
Trent> (and I'm not even a Java guy). :(

It was probably the log4j roots that provided the non-PEP 8 naming. I
suspect the naming could be improved while providing backward compatibility
aliases and deprecating those names.
Sep 8 '05 #6
[sk**@pobox.com wrote]
>> - It's a package, but contrary to any other package I've ever seen,
>> most of its functionality is implemented in __init__.py.
Trent> I'm not defending the implementation, but does this cause any
Trent> particular problems?

No, it just seems symptomatic of some potential organizational problems.
Fair enough. I'm all for having consistent and well structure code in
the stdlib.

>> import logging
>> logging.info('h ello world')
>>
>> ought to just work (implicitly add a stream handler connected to
>> stderr to the root logger).


Trent> Maybe. Unless that causes troubles for real use.

Maybe there's a bug then (or maybe the docs still need work). When I
executed (all of these examples were typed at an interactive prompt):

import logging
logging.info('h ello world')

I get no output. Looking at the doc for the basicConfig() function, I see:

The functions debug(), info(), warning(), error() and critical() will
call basicConfig() automatically if no handlers are defined for the root
logger.


Unfortunately your getting caught by the default logging level being
WARN, so that any log level below that is tossed.

import logging
logging.basicCo nfig()
logging.error(" help!")
logging.warn("s tay away from the river")
logging.info("n ice sunset, eh?")

Running that generates:

ERROR:root:help !
WARNING:root:st ay away from the river
Trent> Having lazy configuration like this means that it can be a subtle
Trent> thing for top-level application code to setup the proper logging
Trent> configuration.

Again, based on my reading of the basicConfig doc, it seems like the logging
package is supposed to already do that.
Sort of. I guess all it implies is that if application code wants
to do special log handler setup then it needs to make sure to work in
the case of basicConfig() having been called and not.

The configuration stuff is quite subtle. The docs need to give
good best practices for a could coverage of reasonable use cases.
Nothing catastrophic will happen with a weird logging configuration --
probably just more log messages that you'd want.

It was probably the log4j roots that provided the non-PEP 8 naming.
Definitely.
I suspect the naming could be improved while providing backward
compatibility aliases and deprecating those names.


Do you mean naming like "makeLogRec ord" etc? I thought PEP 8 said
camelCase (or whatever it is called) was okay?
Trent

--
Trent Mick
Tr****@ActiveSt ate.com
Sep 8 '05 #7

Trent> Unfortunately your getting caught by the default logging level
Trent> being WARN, so that any log level below that is tossed.

Ah, okay. I'll pick back through the docs and see what I missed, then maybe
add a description of the minimal steps needed to get going.
I suspect the naming could be improved while providing backward
compatibility aliases and deprecating those names.


Trent> Do you mean naming like "makeLogRec ord" etc?

Yes.

Trent> I thought PEP 8 said camelCase (or whatever it is called) was
Trent> okay?

Hmmm... In the section entitled "Naming Conventions" I see:

Function Names

Function names should be lowercase, possibly with words separated by
underscores to improve readability. mixedCase is allowed only in
contexts where that's already the prevailing style (e.g. threading.py),
to retain backwards compatibility.

Method Names and Instance Variables

The story is largely the same as with functions: in general, use
lowercase with words separated by underscores as necessary to improve
readability.

Since the logging package currently uses mixedCase it would appear it
shouldn't revert to lower_case. I'm thinking it should have probably used
lower_case from the start though. I see no real reason to have maintained
compatibility with log4j. Similarly, I think PyUnit (aka unittest) should
probably have used lower_case method/function names. After all, someone
went to the trouble of PEP-8-ing the module name when PyUnit got sucked into
the core. Why not the internals as well?

I realize I'm playing the devil's advocate here. If a module that's been
stable outside the core for awhile gets sucked into Python's inner orbit,
gratuitous breakage of the existing users' code should be frowned upon,
otherwise people will be hesitant to be early adopters. There's also the
matter of synchronizing multiple versions of the module (outside and inside
the core). Still, a dual naming scheme with the non-PEP-8 names deprecated
should be possible.

In the case of the logging module I'm not sure that applies. If I remember
correctly, it was more-or-less written for inclusion in the core. In that
case it should probably have adhered to PEP 8 from the start. Maybe going
forward we should be more adamant about that when an external module becomes
a candidate for inclusion in the core.

Skip
Sep 8 '05 #8
[sk**@pobox.com wrote]
Trent> I thought PEP 8 said camelCase (or whatever it is called) was
Trent> okay?

Hmmm... In the section entitled "Naming Conventions" I see:

Function Names

Function names should be lowercase, possibly with words separated by
underscores to improve readability. mixedCase is allowed only in
contexts where that's already the prevailing style (e.g. threading.py),
to retain backwards compatibility.

Method Names and Instance Variables

The story is largely the same as with functions: in general, use
lowercase with words separated by underscores as necessary to improve
readability.
I swear that has changed since I last read that. :)
....checking... Guess I haven't read it in about 2 years. This patch:

Sat Mar 20 06:42:29 2004 UTC (17 months, 2 weeks ago) by kbk

Patch 919256
Clarify and standardize the format for names of modules,
functions, methods, and instance variables.

Consistent, I hope, with discussion on python-dev

http://mail.python.org/pipermail/pyt...ch/043257.html

http://mail.python.org/pipermail/pyt...ch/043259.html

Made this change:

http://cvs.sourceforge.net/viewcvs.p...1=1.20&r2=1.21

Function Names

- Plain functions exported by a module can either use the CapWords
- style or lowercase (or lower_case_with _underscores). There is
- no strong preference, but it seems that the CapWords style is
- used for functions that provide major functionality
- (e.g. nstools.WorldOp en()), while lowercase is used more for
- "utility" functions (e.g. pathhack.kos_ro ot()).
+ Function names should be lowercase, possibly with underscores to
+ improve readability. mixedCase is allowed only in contexts where
+ that's already the prevailing style (e.g. threading.py), to retain
+ backwards compatibility.
Since the logging package currently uses mixedCase it would appear it
shouldn't revert to lower_case. I'm thinking it should have probably used
lower_case from the start though. I see no real reason to have maintained
compatibility with log4j. Similarly, I think PyUnit (aka unittest) should
probably have used lower_case method/function names. After all, someone
went to the trouble of PEP-8-ing the module name when PyUnit got sucked into
the core. Why not the internals as well?
Perhaps because of the timing.

If I remember
correctly, it was more-or-less written for inclusion in the core.


Yah. It was added before Guido more clearly stated that he thought
modules should have a successful life outside the core before being
accepted in the stdlib.

Trent

--
Trent Mick
Tr****@ActiveSt ate.com
Sep 8 '05 #9
sk**@pobox.com wrote:
Perhaps so, but the logging module seems like such an unpythonic beast to
me. How about cleaning it up (*) before we add more to it? Stuff like
colorizing seems like it belongs in its own module (presuming a reasonably
general markup scheme can be agreed upon) so it can be used outside the
logging package.
How is it unpythonic, exactly? I agree that colorizing, etc. is
probably best located in its own module.
(*) Stuff that seems very odd to me:

- It's a package, but contrary to any other package I've ever seen, most
of its functionality is implemented in __init__.py. __init__.py is
roughly four times larger than the next largest (bsddb, which is a
beast because BerkDB has gotten so big over the years and the
module/package has strived to remain backwards-compatible).
I agree that __init__.py is rather large, but I wasn't aware of any
guidelines restricting its size. Having a smaller __init__.py and e.g.
putting the bulk of the code in a subpackage such as logging.core was
considered; I didn't see the point of doing that, though! And the
module certainly received a reasonable amount of peer review on
python-dev before going into the standard library.
- It's still too hard to use. The obvious 'hello world' example

import logging
logging.info('h ello world')

ought to just work (implicitly add a stream handler connected to
stderr to the root logger).
As Trent pointed out in another post, one extra line with a
basicConfig() call would provide the behaviour that you want. This is
surely not too much to have to add. The default level of WARNING was
deliberately chosen to avoid excessive verbosity in the general case.
- Its functionality is partitioned in sometimes odd ways. For example,
it has a handlers module, but what I presume would be the most
commonly used handler (StreamHandler) is not defined there. It's in
(you have three guesses and the first two don't count) __init__.py
instead of in logging.handler s. Consequently, browsing in the obvious
way fails to find the StreamHandler class.
It's partitioned that way so that the most commonly used handlers are
in the core package, and the less commonly used ones are in the
handlers package. This seems reasonable to me - you don't incur the
footprint of the less common handlers just to do console and file based
logging.
- It doesn't use PEP 8 style as far as naming is concerned, instead
doing some sort of Java or C++ or Perl camelCase thing. Eschewing PEP
8 is fine for other stuff, but code in the Python core (especially new
code like the logging module) should strive to adhere to PEP 8, since
many people will use the core code as a pattern for their own code.


I would not have been too unhappy to change the naming to unix_like
rather than CamelCase. Nobody on python-dev asked for it to be done.
The code was mostly written before the idea of putting it into Python
came up - Trent had independently written PEP-282 and I had done a fair
amount of work on the module before getting the idea that, by adhering
to PEP 282, it could be put forward as an addition to the Python
standard library.

Regards,

Vinay

Sep 12 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
3498
by: Pete Jereb | last post by:
Ok, I've managed to get the logging package to work, sort of. I'm writing a text parser, where data entry clerks can edit large, unwieldy and unforgiving textfiles that are VERY SENSITIVE as to where things are located, ie the decimal place MUST BE 15 spaces after the last word on the line. So I'm writing a backend, and a Microsoft Access guru is writing the gui. Once they edit the files by field, the corrected files are sent to a...
0
1349
by: Logan | last post by:
Is there actually a good reason why the StreamHandler and the FileHandler are in the core package and all other handlers are in logging.handlers? I first did not realize this when reading the documentation of the logging package and wrote a script which used: from logging import FileHandler When I changed the script to use the 'RotatingFileHandler', I
0
1659
by: Robert.Schmitt | last post by:
I found that the configuration system of the new logging package of Python 2.3 has some unintuitive idiosyncracies that are worth mentioning because they can cost you quite some development time and are not documented elsewhere. I used the logging configuration file shown below. My aim was to log only the INFO messages, but log DEBUG messages for one particular module (called webTestLogin.py).
1
3696
by: j vickroy | last post by:
My system: MSW XP professional Python 2.3.3 logging package: 0.4.9.2 My problem: The log_test3.py script, provided with the logging package distribution, generates an unexpected message: No handlers could be found for logger "root"
0
4660
by: Joe Bloggs | last post by:
Hi all, I take the pleasure to inform that Dotnet Commons Logging has been released for use. Dotnet Commons Logging, a subproject of the Donet Commons project currently located under the GotDotNet Workspace, has been released as an individual package. Dotnet Commons Logging provides a unified Log interface that acts as a
12
1922
by: Eric S. Johansson | last post by:
I need to to be able to conditionally log based on the method the log statement is in and one other factor like a log level. in order to do so, I need to be able to automatically find out the name of the method and its class but I haven't found out how to do that yet. for example, class catus(Felis): def Siamese_cat( yowl, purr, demand_food):
2
1960
by: Vinay Sajip | last post by:
Some users of the logging package have raised an issue regarding the difficulty of passing additional contextual information when logging. For example, the developer of a networked application may want to log, in addition to specifics related to to the network service being provided, information about the IP address of the remote machine and the username of the person logged into and using the service. Python 2.4 introduced an 'extra'...
4
2362
by: Matthew Wilson | last post by:
I'm working on a package that uses the standard library logging module along with a .cfg file. In my code, I use logging.config.fileConfig('/home/matt/mypackage/matt.cfg') to load in the logging config file. However, it seems really obvious to me that this won't work when I share this package with others.
6
1722
by: Thomas Heller | last post by:
I'm using the logging module in my comtypes library to log 'interesting' things that happen. In other words, the idea is if the user of the library is interested in the details that happen in the package internally, he (she?) would configure a logging level and handlers that write the log messages where it is convenient. This works great, with one exception: If the script using the library does NOT configure logging, and somewhere the...
0
8739
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9384
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9088
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6681
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5995
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4762
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3207
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2602
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2147
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.