Steps to replicate the issue (include links if applicable):
Run the following code:
from pywikibot import Site, Page site = Site("test", "wikipedia") page = Page(site, "Wikipedia:Sandbox") page.put("foo")
What happens?:
It prints to stderr:
Sleeping for 9.6 seconds, 2023-01-10 10:35:00 Page [[test:Wikipedia:Sandbox]] saved
What should have happened instead?:
It should not produce anything on either stdout or stderr
Software version (skip for WMF-hosted wikis like Wikipedia):
pywikibot==7.7.1
Python 3.9.13
Other information (browser name/version, screenshots, etc.):
Poking around you can see that pywikibot has installed its own logging handler:
o "pywiki" | Level Level 11 | Propagate OFF | Handler <TerminalHandler <stderr> (INFO)> | Level INFO | Filter <pywikibot.userinterfaces.terminal_interface_base.MaxLevelFilter object at 0x7fc485a43e80> | Formatter fmt='%(message)s%(newline)s' datefmt=None | Handler <TerminalHandler <stdout> (STDOUT)> | Level STDOUT | Filter <pywikibot.userinterfaces.terminal_interface_base.MaxLevelFilter object at 0x7fc485a43fd0> | Formatter fmt='%(message)s%(newline)s' datefmt=None | Handler <TerminalHandler <stderr> (WARNING)> | Level WARNING | Formatter fmt='%(levelname)s: %(message)s%(newline)s' datefmt=None | | | o<--[pywiki.wiki] | | | o<--"pywiki.wiki.family" | Level NOTSET so inherits level Level 11
Not only does this produce unwanted output to stderr/stdout, the handler is set to not propagate up to the root logger, so I can't even get the output into my application's log file, where I want it. It should not be installing logging handlers when just called as a library. Installing handlers is the purview of the application layer. As stated in the Python language docs:
Note It is strongly advised that you do not add any handlers other than NullHandler to your library’s loggers. This is because the configuration of handlers is the prerogative of the application developer who uses your library. The application developer knows their target audience and what handlers are most appropriate for their application: if you add handlers ‘under the hood’, you might well interfere with their ability to carry out unit tests and deliver logs which suit their requirements.
The handlers should be installed by the individual scripts, or perhaps in the pwb wrapper script. You could provide a pywikibot.logging.init_handlers() which a user could call to get the current behavior. Or, at the very least, pywikibot.logging.inhibit_handlers() which could be called by a developer using the library to prevent the handlers from being installed. Note that once a handler is installed, there's no good way for an application to remove it.