classification
Title: Documentation - default for StreamHandler
Type: Stage: resolved
Components: Documentation Versions: Python 3.9
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: docs@python Nosy List: docs@python, jonathan-lp, vinay.sajip
Priority: normal Keywords:

Created on 2019-07-11 14:14 by jonathan-lp, last changed 2019-07-13 16:55 by jonathan-lp. This issue is now closed.

Messages (9)
msg347677 - (view) Author: Jonathan (jonathan-lp) Date: 2019-07-11 14:14
https://docs.python.org/2/library/logging.handlers.html
https://docs.python.org/3/library/logging.handlers.html

Both say:

"""class logging.StreamHandler(stream=None)

Returns a new instance of the StreamHandler class. If stream is specified, the instance will use it for logging output; otherwise, sys.stderr will be used."""

Surely that means from an user perspective that the default is actually `sys.stderr`, not `None`?
msg347685 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2019-07-11 14:59
If None is passed, that is interpreted to mean whatever the implementation default is, and that is sys.stderr. For backwards compatibility, that won't change: and I don't see any need to update the documentation, as it makes it perfectly clear that sys.stderr will be used if None is specified. Nor do I see a need to change the default parameter value from its current value of None.
msg347687 - (view) Author: Jonathan (jonathan-lp) Date: 2019-07-11 15:11
> If None is passed, that is interpreted to mean whatever the implementation default is, and that is sys.stderr.
Unless I'm missing something, this means that sys.stderr is functionally the default, which means it is the default. We users don't care about implementation details; this documentation is for users, not implementers.

This is how other parts of the same docs work. e.g.:
"""
class logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0)
...If mode is not specified, 'a' is used...
"""


"""
class logging.handlers.SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER, socktype=socket.SOCK_DGRAM)
...If address is not specified, ('localhost', 514) is used...
If facility is not specified, LOG_USER is used... 
"""

There's a standard for documenting defaults for keyword arguments, I would ask that it please be used consistently to help us users.
msg347736 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2019-07-12 10:17
The devil is in the detail. If stream=sys.stderr is specified, that takes effect at import time. If stream=None is specified and the implementation chooses to treat that as sys.stderr, that takes effect at the time of the call. The two are not equivalent. It was a conscious choice by me to implement it this way, and I believe it's clearly documented what happens, which should be sufficiently clear for users.

Which part of

"If stream is specified, the instance will use it for logging output; otherwise, sys.stderr will be used."

is unclear?
msg347787 - (view) Author: Jonathan (jonathan-lp) Date: 2019-07-13 08:38
> The devil is in the detail. If stream=sys.stderr is specified, that takes effect at import time. If stream=None is specified and the implementation chooses to treat that as sys.stderr, that takes effect at the time of the call. The two are not equivalent.

But this isn't what the prose says at all. You're right, the prose clearly say that the default is sys.stderr, however the code doesn't show that, and many people won't read the prose (I don't a lot of the time), they'll only look at the code snippet because that's all they think they need. The code-snippet claims that the default is None, which from a user perspective isn't true.

Again I point out that the documentation is for users, not implementers. We users Do. Not. Care. about how wonderfully clever your implementation is, we care about how it actually works. Whatever Rube-Goldbergian implementation details there are behind the scenes are of no interest to us.

Yet again:
There's a standard for documenting defaults for keyword arguments, I would ask that it please be used consistently to help us users.

Fine, lets try this another way - does anyone else have opinions on this? What's the convention for documentation defaults?
msg347793 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2019-07-13 10:10
> the prose clearly say that the default is sys.stderr, however the code doesn't show that

Which code are you looking at? Here is the entirety of StreamHandler.__init__:

    def __init__(self, stream=None):
        """
        Initialize the handler.
        If stream is not specified, sys.stderr is used.
        """
        Handler.__init__(self)
        if stream is None:
            stream = sys.stderr
        self.stream = stream

> We users Do. Not. Care. about how wonderfully clever your implementation is, we care about how it actually works. Whatever Rube-Goldbergian implementation details there are behind the scenes are of no interest to us.

I'm not sure your tone is particularly constructive here. I don't regard the code you say you've read, reproduced above, is particularly Rube-Goldbergian, or even Heath-Robinsonish. And are you presuming to speak for all Python users here?

> Fine, lets try this another way - does anyone else have opinions on this?

As far as I can remember, you're the first person to bring this up since logging was added to Python in 2003. In all that time, no-one appears to have been confused by that prose, which has been there since pretty much the beginning, though there was a spelling change and a logging documentation reorganisation around 9 years ago.
msg347799 - (view) Author: Jonathan (jonathan-lp) Date: 2019-07-13 10:25
> I'm not sure your tone is particularly constructive here.
Apologies, my bad.

> Which code are you looking at?
The documentation code: `class logging.StreamHandler(stream=None)`. Sorry, I don't know what you'd call that. I'm not referring to the code proper.

> As far as I can remember, you're the first person to bring this up since logging was added to Python in 2003.
This is a fallacy. Just because no-one else has reported it doesn't mean it hasn't caused a problem. 
I mean, I'm sure there are plenty of spelling errors/typos in the docs that no-one has reported for years, it doesn't mean they shouldn't be fixed when raised.
It's also assuming you have seen and remember every single bug report related to this from the past 16 years which, nothing personal, seems incredibly unlikely given how poor humans are at remembering things in the first place.

> And are you presuming to speak for all Python users here?
I'm presuming to speak for end-users yes, why not? I did ask for other input too you'll note. After a few decades of practice I'm fairly decent at getting into the headspace of users (of which I am one in this case), and I know it's something many developers don't really do well. A common mistake we developers make is to assume that everyone knows what we know and thinks like us.
msg347846 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2019-07-13 16:48
> This is a fallacy.

What fallacy? I was responding to "does anyone else have opinions on this?" I can't read minds of people all over the world, so I have to go by my best guess, which is based on how many times this issue has been reported before - which I believe is zero.

> It's also assuming you have seen and remember every single bug report related to this from the past 16 years which, nothing personal, seems incredibly unlikely given how poor humans are at remembering things in the first place.

Feel free to do a search on here to see if you can find an earlier issue about this.

> I'm presuming to speak for end-users yes, why not? 

Because they're a very diverse bunch who don't all speak with one voice. I, too, am a user (of other people's code) as much as a developer. I don't see things the same way as you do, here, and it's not because it's my code. I'd probably feel the same way if you'd pointed to some other instance of Python code which does the same kind of thing.

There are numerous examples in the stdlib where None is passed in and some other value (e.g. 'utf-8' for an encoding) are used as a default, without that value appearing in any documented argument list.
msg347847 - (view) Author: Jonathan (jonathan-lp) Date: 2019-07-13 16:55
>What fallacy?
You appeared to be saying (to paraphrase) "no-one else has ever reported this, so it's never been a problem". That's a fallacy.

> I was responding to "does anyone else have opinions on this?"
I was asking if anyone else wanted to chime in with an opinion.

> There are numerous examples in the stdlib where None is passed in and some other value (e.g. 'utf-8' for an encoding) are used as a default
Then for clarity's purpose I'd suggest those be changed too, but that's another ticket.
History
Date User Action Args
2019-07-13 16:55:17jonathan-lpsetmessages: + msg347847
2019-07-13 16:48:08vinay.sajipsetmessages: + msg347846
2019-07-13 10:25:59jonathan-lpsetmessages: + msg347799
2019-07-13 10:10:51vinay.sajipsetmessages: + msg347793
2019-07-13 08:38:13jonathan-lpsetmessages: + msg347787
2019-07-12 10:17:14vinay.sajipsetstatus: open -> closed
resolution: not a bug
messages: + msg347736
2019-07-11 15:12:02jonathan-lpsetstatus: open
2019-07-11 15:11:25jonathan-lpsetstatus: closed -> (no value)
resolution: not a bug -> (no value)
messages: + msg347687
2019-07-11 14:59:50vinay.sajipsetstatus: open -> closed
resolution: not a bug
messages: + msg347685

stage: resolved
2019-07-11 14:16:02xtreaksetnosy: + vinay.sajip
2019-07-11 14:14:34jonathan-lpcreate