Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #68379 > unrolled thread
| Started by | Tim Chase <python.list@tim.thechases.com> |
|---|---|
| First post | 2014-03-15 21:58 -0500 |
| Last post | 2014-03-16 13:50 -0500 |
| Articles | 8 — 4 participants |
Back to article view | Back to comp.lang.python
Clearing out handlers in logging? Tim Chase <python.list@tim.thechases.com> - 2014-03-15 21:58 -0500
Re: Clearing out handlers in logging? Gunther Dietrich <gd.usenet@spamfence.net> - 2014-03-16 09:39 +0100
Re: Clearing out handlers in logging? Chris Angelico <rosuav@gmail.com> - 2014-03-16 20:02 +1100
Re: Clearing out handlers in logging? Peter Otten <__peter__@web.de> - 2014-03-16 10:18 +0100
Re: Clearing out handlers in logging? Chris Angelico <rosuav@gmail.com> - 2014-03-16 20:35 +1100
Re: Clearing out handlers in logging? Tim Chase <python.list@tim.thechases.com> - 2014-03-16 07:57 -0500
Re: Clearing out handlers in logging? Gunther Dietrich <gd.usenet@spamfence.net> - 2014-03-16 19:29 +0100
Re: Clearing out handlers in logging? Tim Chase <python.list@tim.thechases.com> - 2014-03-16 13:50 -0500
| From | Tim Chase <python.list@tim.thechases.com> |
|---|---|
| Date | 2014-03-15 21:58 -0500 |
| Subject | Clearing out handlers in logging? |
| Message-ID | <mailman.8159.1394938715.18130.python-list@python.org> |
The current (2.7; maybe 3.x?) logging module doesn't have any sort of "clear out all the current handlers" method. I can hack it by doing log = logging.getLogger() # get the root logger del log.handlers[:] # reach inside and nuke 'em log.addHandler(...) # install the one(s) I want but it feels a little dirty to reach into logging.root.handlers since there are other methods for adding/removing handlers. However, as best I can tell, to remove a handler, you already need to have it saved somewhere. Is there a better way to do this, or do I just suck it up and deal with the (potentially thread-ignorant, as it doesn't lock) hack? Thanks, -tkc
[toc] | [next] | [standalone]
| From | Gunther Dietrich <gd.usenet@spamfence.net> |
|---|---|
| Date | 2014-03-16 09:39 +0100 |
| Message-ID | <gd.usenet-B1805D.09394016032014@dwarf.main.lan> |
| In reply to | #68379 |
Tim Chase <python.list@tim.thechases.com> wrote: >The current (2.7; maybe 3.x?) logging module doesn't have any sort of >"clear out all the current handlers" method. Indeed, THERE IS a removeHandler() method. In the documentation of python 2.6, it is mentioned in '16.6.5. Logger Objects', directly after the addHandler() method. If you found the addHandler() method there, you should have found removeHandler() too. And a simple >>> dir(log) ['__doc__', '__init__', '__module__', '_log', 'addFilter', 'addHandler', 'callHandlers', 'critical', 'debug', 'disabled', 'error', 'exception', 'fatal', 'filter', 'filters', 'findCaller', 'getEffectiveLevel', 'handle', 'handlers', 'info', 'isEnabledFor', 'level', 'log', 'makeRecord', 'manager', 'name', 'parent', 'propagate', 'removeFilter', 'removeHandler', 'root', 'setLevel', 'warn', 'warning'] also would have revealed it to you. >I can hack it by doing > > log = logging.getLogger() # get the root logger > del log.handlers[:] # reach inside and nuke 'em > log.addHandler(...) # install the one(s) I want > >but it feels a little dirty to reach into logging.root.handlers since >there are other methods for adding/removing handlers. However, as >best I can tell, to remove a handler, you already need to have it >saved somewhere. What about this: >>> for handler in log.handlers: ... log.removeHandler(handler) I think, that's just one of the tasks that removeHandler() was written for. >Is there a better way to do this, or do I just suck it up and deal >with the (potentially thread-ignorant, as it doesn't lock) hack? One of the best ways would be to read the documentation. And to do some exploration, e.g. by means of dir() and help(), could also be quite instructive. This experience cannot be replaced by documentation-research requests to the Usenet. Best regards, Gunther
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-03-16 20:02 +1100 |
| Message-ID | <mailman.8163.1394960581.18130.python-list@python.org> |
| In reply to | #68387 |
On Sun, Mar 16, 2014 at 7:39 PM, Gunther Dietrich <gd.usenet@spamfence.net> wrote: >>but it feels a little dirty to reach into logging.root.handlers since >>there are other methods for adding/removing handlers. However, as >>best I can tell, to remove a handler, you already need to have it >>saved somewhere. > > What about this: > >>>> for handler in log.handlers: > ... log.removeHandler(handler) > > I think, that's just one of the tasks that removeHandler() was written > for. I'm sure Tim was aware of the removeHandler function. But this is still reaching into log.handlers - although IMO it's safer to reach in and read than to reach in and mutate. So without the implications of Tim's inability to read docs, this is a viable suggestion. I'd prefer this over the original "del log.handlers[:]". ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2014-03-16 10:18 +0100 |
| Message-ID | <mailman.8164.1394961511.18130.python-list@python.org> |
| In reply to | #68387 |
Gunther Dietrich wrote:
> Tim Chase <python.list@tim.thechases.com> wrote:
>
>>The current (2.7; maybe 3.x?) logging module doesn't have any sort of
>>"clear out all the current handlers" method.
>
> Indeed, THERE IS a removeHandler() method. In the documentation of
> python 2.6, it is mentioned in '16.6.5. Logger Objects', directly after
> the addHandler() method. If you found the addHandler() method there, you
> should have found removeHandler() too.
>
> And a simple
>
>>>> dir(log)
> ['__doc__', '__init__', '__module__', '_log', 'addFilter', 'addHandler',
> 'callHandlers', 'critical', 'debug', 'disabled', 'error', 'exception',
> 'fatal', 'filter', 'filters', 'findCaller', 'getEffectiveLevel',
> 'handle', 'handlers', 'info', 'isEnabledFor', 'level', 'log',
> 'makeRecord', 'manager', 'name', 'parent', 'propagate', 'removeFilter',
> 'removeHandler', 'root', 'setLevel', 'warn', 'warning']
>
> also would have revealed it to you.
>
>
>>I can hack it by doing
>>
>> log = logging.getLogger() # get the root logger
>> del log.handlers[:] # reach inside and nuke 'em
>> log.addHandler(...) # install the one(s) I want
>>
>>but it feels a little dirty to reach into logging.root.handlers since
>>there are other methods for adding/removing handlers. However, as
>>best I can tell, to remove a handler, you already need to have it
>>saved somewhere.
>
> What about this:
>
>>>> for handler in log.handlers:
> ... log.removeHandler(handler)
>
> I think, that's just one of the tasks that removeHandler() was written
> for.
>
>
>>Is there a better way to do this, or do I just suck it up and deal
>>with the (potentially thread-ignorant, as it doesn't lock) hack?
>
> One of the best ways would be to read the documentation. And to do some
> exploration, e.g. by means of dir() and help(), could also be quite
> instructive. This experience cannot be replaced by
> documentation-research requests to the Usenet.
Hm, what do the docs say about this one?
>>> import logging
>>> logging.basicConfig()
>>> log = logging.getLogger("foo")
>>> for i in range(5):
... log.addHandler(logging.FileHandler("tmp.log"))
...
>>> assert len(log.handlers) == 5
>>> for handler in log.handlers:
... log.removeHandler(handler)
...
>>> log.handlers
[<logging.FileHandler object at 0x7f8217686e90>, <logging.FileHandler object
at 0x7f8216f9eb90>]
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-03-16 20:35 +1100 |
| Message-ID | <mailman.8165.1394962522.18130.python-list@python.org> |
| In reply to | #68387 |
On Sun, Mar 16, 2014 at 8:18 PM, Peter Otten <__peter__@web.de> wrote:
> Hm, what do the docs say about this one?
>
>>>> import logging
>>>> logging.basicConfig()
>>>> log = logging.getLogger("foo")
>>>> for i in range(5):
> ... log.addHandler(logging.FileHandler("tmp.log"))
> ...
>>>> assert len(log.handlers) == 5
>>>> for handler in log.handlers:
> ... log.removeHandler(handler)
> ...
>>>> log.handlers
> [<logging.FileHandler object at 0x7f8217686e90>, <logging.FileHandler object
> at 0x7f8216f9eb90>]
for handler in log.handlers[:]:
log.removeHandler(handler)
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Tim Chase <python.list@tim.thechases.com> |
|---|---|
| Date | 2014-03-16 07:57 -0500 |
| Message-ID | <mailman.8167.1394974663.18130.python-list@python.org> |
| In reply to | #68387 |
On 2014-03-16 09:39, Gunther Dietrich wrote:
> Tim Chase <python.list@tim.thechases.com> wrote:
>
> >The current (2.7; maybe 3.x?) logging module doesn't have any sort
> >of "clear out all the current handlers" method.
>
> Indeed, THERE IS a removeHandler() method.
Yes, I'm aware of it, having read the source & docs. However, the
signature is
removeHandler(some_handle_to_a_handler_that_you_already_have)
and at the point in my code where I need to override this,
basicConfig() has already assigned a default stream handler and
discarded the handle/name/reference to it because
the .debug/.info/.warn/.error/.critical methods of all call
basicConfig() if there aren't any handlers.
[Aside: which is non-pythonically, using "if len(self.handlers) == 0"
instead of "if not self.handlers" in addition to the camel-case
naming (which would be much harder to fix)]
> >>> for handler in log.handlers:
> ... log.removeHandler(handler)
>
> I think, that's just one of the tasks that removeHandler() was
> written for.
The question revolves mostly around dipping your hands into the
undocumented .handlers property. I can nuke it directly (and looking
at least at the 2.7 source, there doesn't seem to be much issue with
doing this), or I can iterate (as modified by Chris Angelico to
prevent modifying the list over which you're iterating). Either way,
it still involves reaching into log.handlers which doesn't appear in
any of the documentation as far as I could find.
So yes, I use help() and dir() on a daily basis. But just because
something is there doesn't mean I should go mucking with it in the
event it's undocumented. If it *should* be trusted as a publicly
available interface, it should be documented; if it shouldn't be
treated publicly, then it should have a way to iterate over them
such as
def iterHandlers(self):
for h in self.handlers[:]:
yield h
so you can do
for h in log.iterHandlers():
log.removeHandler(h)
Given how stable this code has been over the years, I'd just document
the log.handlers property and possibly advise to lock around messing
with it (unless "del log.handlers[:]" is atomic).
-tkc
[toc] | [prev] | [next] | [standalone]
| From | Gunther Dietrich <gd.usenet@spamfence.net> |
|---|---|
| Date | 2014-03-16 19:29 +0100 |
| Message-ID | <gd.usenet-EA8AA5.19294616032014@dwarf.main.lan> |
| In reply to | #68393 |
Tim Chase <python.list@tim.thechases.com> wrote: >> >The current (2.7; maybe 3.x?) logging module doesn't have any sort >> >of "clear out all the current handlers" method. >> >> Indeed, THERE IS a removeHandler() method. > >Yes, I'm aware of it, having read the source & docs. However, the >signature is Sorry, your original article lacks information about what you already know/tried and what not. So it is a bit misleading and makes the impression, you would't read the documentation. It would have been helpful if you had told us your preconditions. Best regards, Gunther
[toc] | [prev] | [next] | [standalone]
| From | Tim Chase <python.list@tim.thechases.com> |
|---|---|
| Date | 2014-03-16 13:50 -0500 |
| Message-ID | <mailman.8172.1394995811.18130.python-list@python.org> |
| In reply to | #68397 |
On 2014-03-16 19:29, Gunther Dietrich wrote: > >> Indeed, THERE IS a removeHandler() method. > > > >Yes, I'm aware of it, having read the source & docs. However, the > >signature is > > Sorry, your original article lacks information about what you > already know/tried and what not. So it is a bit misleading and > makes the impression, you would't read the documentation. It would > have been helpful if you had told us your preconditions. Heh, I tried to make that clear in my initial posting with the "since there are other methods for adding/removing handlers" bit. I guess I could have been more explicit though as to what I'd tried. I generally figure that, if someone knows enough to dig into the stdlib's source code, they also know enough to use dir() and help(). Not *always* the case, but a good hint that they're past the basics. But I could have clarified my question more along the lines of "Should log.handlers be public/documented; should Logger grow clearHandlers() and iterHandlers() methods; or should I wantonly use log.handlers but then just get to keep both pieces if/when it breaks?" -tkc
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web