Issue 876421: logging handlers raise exception on level (original) (raw)

Issue876421

Created on 2004-01-13 22:04 by jimjjewett, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (10)
msg19675 - (view) Author: Jim Jewett (jimjjewett) Date: 2004-01-13 22:04
logging.__version__ = "0.4.8.1" - matches CVS Handler() takes a keyword argument of level, for the initial level of message it should care about. StreamHandler inherits from Handler, but does not pass the level keyword through when calling Handler__init__. #def __init__(self, strm=None): def __init__(self, strm=None, **kwargs): #Handler.__init__(self) # should we delete the key that Stream uses? Handler.__init__(self, **kwargs) I am submitting as a bug rather than a patch because several other classes have the same problem, and because I am not sure whether arguments used by the child initializer (such as strm) should be passed on.
msg19676 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2004-01-18 19:02
Logged In: YES user_id=308438 I don't think this is a bug. You should consider that Handler.__init__() takes a level argument with a default value, rather than a keyword argument. This should be treated as an internal implementation detail, used only by subclasses of Handler. If you are writing a Handler subclass, you can pass the level argument via your HandlerSubclass.__init__() to Handler.__init__(). Otherwise, you can set the level using Handler.setLevel().
msg19677 - (view) Author: Jim Jewett (jimjjewett) Date: 2004-01-19 17:57
Logged In: YES user_id=764593 In general, it seems odd that Class(arg=val) would work, but subClass(arg=val) would fail, unless subclass is designed explicitly to restrict capabilities. logfile = logging.Handler(level=logging.ERROR) works.[1] logfile = logging.StreamHandler(level=logging.ERROR) fails, even though the level is still relevant and reasonable. If I submit a patch for the classes distributed with the library, would it be an acceptable change? [1] Admittedly, this handler might fail later, because Handler. emit() assumes that Handler is abstract.
msg19678 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2004-01-22 23:19
Logged In: YES user_id=308438 It's not really odd that Class(arg=val) would work, but subClass(arg=val) would fail. This is because there is no requirement that base class constructors and derived class constructors need to look the same. Of course, the derived class needs to understand how to construct the base class. Please note that the Handler class is a base class, not intended to be instantiated - as you know. So your example is not really valid. Please don't submit a patch for this, it's not a bug. I still don't understand why you can't use setLevel() to set your level. Why does it *have* to be in the constructor?
msg19679 - (view) Author: Jim Jewett (jimjjewett) Date: 2004-01-23 22:23
Logged In: YES user_id=764593 One reason to use a standard library is so that my own code won't have to worry about any more detail than I want to -- I shouldn't even have to read the code within the library for implementation details. The more study required/glue code needed/state I must keep, the less useful the library is. Keeping a reference and using setLevel is a workaround, but it should not be required. I should be able to set up a handler in one line. For example, to log everything and echo important stuff to the user: logging.addHandler(StreamHandler(level=ERROR)) logging.addHandler(RotatingFileHandler("mylog",level=DEBUG)) (note that the level=DEBUG is only required because the default of 0 really turns into WARNING if I don't reset it.)
msg19680 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2004-01-23 22:53
Logged In: YES user_id=308438 I'm sorry if you don't find the library very useful. I don't regard using setLevel() as a workaround - it was designed this way. Not all designers would design things the same way. You are the first and only person to raise this issue, after many months during which the library has been in use (even before Python 2.3 was released). If many people raise this as an issue, I will have to rethink this - but right now I don't think making a change is justified. I certainly haven't regarded the "set up a hander in one line" as a design goal. If you use a configuration file, you can set up multiple handlers, formatters and loggers in just one or two lines of code. (Not that I am recommending using a configuration file - but the functionality is there). Thanks for taking the time to put your point of view, though. I genuinely appreciate it.
msg109484 - (view) Author: Mickey Killianey (Mickey.Killianey) Date: 2010-07-07 17:02
Would you be willing to consider supporting the level keyword as a convenience for the most simple/common Handlers? (For example, maybe just StreamHandler and FileHandler?)
msg109836 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2010-07-10 09:00
If I did this for some but not handler classes, then people would probably log issues saying e.g. "Why doesn't NTEventLogHandler" support a level argument? Other handlers do." etc. What's the big problem with using setLevel() to set the level? If you're after convenience, you could use the dictionary configuration API which allows you to set the levels declaratively.
msg110162 - (view) Author: Mickey Killianey (Mickey.Killianey) Date: 2010-07-13 09:01
Vinay: thanks for the response. My use case is that I've inherited a legacy application with a problematic third-party module (call it 'foo'). I want to sprinkle in some file-logging for the 'foo' logger to trace what's going on, while making the minimal impact on the module. Since 'foo' does some reflection on itself, I also want to avoid introducing new symbols in the module, if possible. You said: > If you're after convenience, you could use the dictionary > configuration API which allows you to set the levels > declaratively. If by "dictionary configuration API" you're suggesting logging.config.dictConfig, then yes, it does meet my criteria, although the minimal amount of code to configure one file handler looks pretty long-winded for what seems like a fairly common request: logging.config.dictConfig({ 'version' : 1, 'handlers' : { 'handler_name' : { 'class' : 'logging.FileHandler', 'level' : logging.DEBUG, 'filename' : 'foo.log', }, }, 'loggers' : { 'foo' : { 'handlers' : [ 'handler_name', ], }, }, }) Or were you suggesting logging.basicConfig? The limitation of basicConfig seems to be that it only works on an unconfigured root logger, not on a named logger, and it doesn't work if anyone else has touched root. I was hoping for something that's simple, easy-to-remember, easy-to-type, and makes a minimal impact on the module I'm debugging. For example, how do any of these sound...? ...if basicConfig had an optional 'name' argument, so that it could config loggers other than root logger: logging.basicConfig(name='foo', filename='foo.log', level=DEBUG) ...if 'basicConfig' was a method on Logger: logging.getLogger('foo').basicConfig(filename='foo.log', level=DEBUG) ...if the handlers' setters supported the builder pattern and returned self from setLevel: logging.getLogger('foo').addHandler(FileHandler('foo.log').setLevel(DEBUG)) (Instead of commenting on this closed bug, should I enter this as a new issue and set it as a feature request?)
msg110200 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2010-07-13 14:54
----- Original Message ---- > Mickey Killianey <mickey.killianey@gmail.com> added the comment: > > Or were you suggesting logging.basicConfig? The limitation of basicConfig >seems to be that it only works on an unconfigured root logger, not on a named >logger, and it doesn't work if anyone else has touched root. True, but if you use basicConfig to configure the root logger, descendant loggers (such as 'foo') will use those handlers. Of course, if someone else has configured a handler for the root logger already, then you may not be able to use this. > > I was hoping for something that's simple, easy-to-remember, easy-to-type, and >makes a minimal impact on the module I'm debugging. For example, how do any of >these sound...? > > ...if basicConfig had an optional 'name' argument, so that it could config >loggers other than root logger: > > logging.basicConfig(name='foo', filename='foo.log', level=DEBUG) > > ...if 'basicConfig' was a method on Logger: > > logging.getLogger('foo').basicConfig(filename='foo.log', level=DEBUG) > > ...if the handlers' setters supported the builder pattern and returned self >from setLevel: > > logging.getLogger('foo').addHandler(FileHandler('foo.log').setLevel(DEBUG)) > > > (Instead of commenting on this closed bug, should I enter this as a new issue >and set it as a feature request?) > I'd like to avoid making the kinds of changes which are stylistic in nature; the existing APIs will need to remain for backward compatiblity reasons, and I don't want to add the same functionality using different idioms based on what are essentially stylistic preferences. Also, remember that Python 2.x is essentially frozen in terms of new releases (as 2.7 has been released and no 2.8 is planned) so any API changes would apply to 3.2 and later only - I'm guessing you're still on Python 2.x if you're using a legacy application. When all's said and done, to configure a logger for 'foo' with a FileHandler and a specific level will not require more than a few lines of code, so I'd just go ahead and code them up and not worry about trying to get the whole thing to fit on a single line :-) Regards, Vinay Sajip .
History
Date User Action Args
2022-04-11 14:56:02 admin set github: 39817
2010-07-13 14:54:42 vinay.sajip set messages: +
2010-07-13 09:01:49 Mickey.Killianey set messages: +
2010-07-10 09:00:54 vinay.sajip set messages: +
2010-07-07 17:02:12 Mickey.Killianey set nosy: + Mickey.Killianeymessages: +
2004-01-13 22:04:55 jimjjewett create