Skip to content

Commit cf67d6a

Browse files
corona10vsajip
authored andcommitted
bpo-33897: Add a 'force' keyword argument to logging.basicConfig(). (GH-7873)
1 parent 2af9f5d commit cf67d6a

File tree

4 files changed

+46
-3
lines changed

4 files changed

+46
-3
lines changed

Doc/library/logging.rst

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1131,7 +1131,7 @@ functions.
11311131
if no handlers are defined for the root logger.
11321132

11331133
This function does nothing if the root logger already has handlers
1134-
configured for it.
1134+
configured, unless the keyword argument *force* is set to ``True``.
11351135

11361136
.. note:: This function should be called from the main thread
11371137
before other threads are started. In versions of Python prior to
@@ -1183,6 +1183,15 @@ functions.
11831183
| | with 'filename' or 'stream' - if both are |
11841184
| | present, a ``ValueError`` is raised. |
11851185
+--------------+---------------------------------------------+
1186+
| ``force`` | If this keyword argument is specified as |
1187+
| | true, any existing handlers attached to the |
1188+
| | root logger are removed and closed, before |
1189+
| | carrying out the configuration as specified |
1190+
| | by the other arguments. |
1191+
+--------------+---------------------------------------------+
1192+
1193+
.. versionchanged:: 3.8
1194+
The ``force`` argument was added.
11861195

11871196
.. versionchanged:: 3.2
11881197
The ``style`` argument was added.

Lib/logging/__init__.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,7 +1793,8 @@ def basicConfig(**kwargs):
17931793
Do basic configuration for the logging system.
17941794
17951795
This function does nothing if the root logger already has handlers
1796-
configured. It is a convenience method intended for use by simple scripts
1796+
configured, unless the keyword argument *force* is set to ``True``.
1797+
It is a convenience method intended for use by simple scripts
17971798
to do one-shot configuration of the logging package.
17981799
17991800
The default behaviour is to create a StreamHandler which writes to
@@ -1821,13 +1822,19 @@ def basicConfig(**kwargs):
18211822
handlers, which will be added to the root handler. Any handler
18221823
in the list which does not have a formatter assigned will be
18231824
assigned the formatter created in this function.
1824-
1825+
force If this keyword is specified as true, any existing handlers
1826+
attached to the root logger are removed and closed, before
1827+
carrying out the configuration as specified by the other
1828+
arguments.
18251829
Note that you could specify a stream created using open(filename, mode)
18261830
rather than passing the filename and mode in. However, it should be
18271831
remembered that StreamHandler does not close its stream (since it may be
18281832
using sys.stdout or sys.stderr), whereas FileHandler closes its stream
18291833
when the handler is closed.
18301834
1835+
.. versionchanged:: 3.8
1836+
Added the ``force`` parameter.
1837+
18311838
.. versionchanged:: 3.2
18321839
Added the ``style`` parameter.
18331840
@@ -1842,6 +1849,11 @@ def basicConfig(**kwargs):
18421849
# basicConfig() from multiple threads
18431850
_acquireLock()
18441851
try:
1852+
force = kwargs.pop('force', False)
1853+
if force:
1854+
for h in root.handlers[:]:
1855+
root.removeHandler(h)
1856+
h.close()
18451857
if len(root.handlers) == 0:
18461858
handlers = kwargs.pop("handlers", None)
18471859
if handlers is None:

Lib/test/test_logging.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3901,6 +3901,27 @@ def test_handlers(self):
39013901
self.assertIs(handlers[2].formatter, f)
39023902
self.assertIs(handlers[0].formatter, handlers[1].formatter)
39033903

3904+
def test_force(self):
3905+
old_string_io = io.StringIO()
3906+
new_string_io = io.StringIO()
3907+
old_handlers = [logging.StreamHandler(old_string_io)]
3908+
new_handlers = [logging.StreamHandler(new_string_io)]
3909+
logging.basicConfig(level=logging.WARNING, handlers=old_handlers)
3910+
logging.warning('warn')
3911+
logging.info('info')
3912+
logging.debug('debug')
3913+
self.assertEqual(len(logging.root.handlers), 1)
3914+
logging.basicConfig(level=logging.INFO, handlers=new_handlers,
3915+
force=True)
3916+
logging.warning('warn')
3917+
logging.info('info')
3918+
logging.debug('debug')
3919+
self.assertEqual(len(logging.root.handlers), 1)
3920+
self.assertEqual(old_string_io.getvalue().strip(),
3921+
'WARNING:root:warn')
3922+
self.assertEqual(new_string_io.getvalue().strip(),
3923+
'WARNING:root:warn\nINFO:root:info')
3924+
39043925
def _test_log(self, method, level=None):
39053926
# logging.root has no handlers so basicConfig should be called
39063927
called = []
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added a 'force' keyword argument to logging.basicConfig().

0 commit comments

Comments
 (0)