Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
bpo-37111: Added optional encoding parameter to basicConfig.
  • Loading branch information
vsajip committed Jun 9, 2019
commit 794e0a596fd28367298b6b5f3852206dcde8f443
4 changes: 3 additions & 1 deletion Doc/howto/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,11 @@ look at that next. Be sure to try the following in a newly-started Python
interpreter, and don't just continue from the session described above::

import logging
logging.basicConfig(filename='example.log',level=logging.DEBUG)
logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
logging.error('And non-ASCII stuff, too, like Øresund and Malmö')

And now if we open the file and look at what we have, we should find the log
messages:
Expand All @@ -141,6 +142,7 @@ messages:
DEBUG:root:This message should go to the log file
INFO:root:So should this
WARNING:root:And this, too
ERROR:root:And non-ASCII stuff, too, like Øresund and Malmö

This example also shows how you can set the logging level which acts as the
threshold for tracking. In this case, because we set the threshold to
Expand Down
8 changes: 8 additions & 0 deletions Doc/library/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,11 @@ functions.
| | carrying out the configuration as specified |
| | by the other arguments. |
+--------------+---------------------------------------------+
| *encoding* | If this keyword argument is specified along |
| | with *filename*, its value is used when the |
| | FileHandler is created, and thus used when |
| | opening the output file. |
+--------------+---------------------------------------------+

.. versionchanged:: 3.2
The *style* argument was added.
Expand All @@ -1209,6 +1214,9 @@ functions.
.. versionchanged:: 3.8
The *force* argument was added.

.. versionchanged:: 3.9
The *encoding* argument was added.

.. function:: shutdown()

Informs the logging system to perform an orderly shutdown by flushing and
Expand Down
20 changes: 14 additions & 6 deletions Lib/logging/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2001-2017 by Vinay Sajip. All Rights Reserved.
# Copyright 2001-2019 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
Expand All @@ -18,7 +18,7 @@
Logging package for Python. Based on PEP 282 and comments thereto in
comp.lang.python.

Copyright (C) 2001-2017 Vinay Sajip. All Rights Reserved.
Copyright (C) 2001-2019 Vinay Sajip. All Rights Reserved.

To use, simply 'import logging' and log away!
"""
Expand Down Expand Up @@ -1928,15 +1928,16 @@ def basicConfig(**kwargs):
attached to the root logger are removed and closed, before
carrying out the configuration as specified by the other
arguments.
encoding If specified together with a filename, this encoding is passed to
the created FileHandler, causing it to be used when the file is
opened.

Note that you could specify a stream created using open(filename, mode)
rather than passing the filename and mode in. However, it should be
remembered that StreamHandler does not close its stream (since it may be
using sys.stdout or sys.stderr), whereas FileHandler closes its stream
when the handler is closed.

.. versionchanged:: 3.8
Added the ``force`` parameter.

.. versionchanged:: 3.2
Added the ``style`` parameter.

Expand All @@ -1946,12 +1947,19 @@ def basicConfig(**kwargs):
``filename``/``filemode``, or ``filename``/``filemode`` specified
together with ``stream``, or ``handlers`` specified together with
``stream``.

.. versionchanged:: 3.8
Added the ``force`` parameter.

.. versionchanged:: 3.9
Added the ``encoding`` parameter.
"""
# Add thread safety in case someone mistakenly calls
# basicConfig() from multiple threads
_acquireLock()
try:
force = kwargs.pop('force', False)
encoding = kwargs.pop('encoding', None)
if force:
for h in root.handlers[:]:
root.removeHandler(h)
Expand All @@ -1970,7 +1978,7 @@ def basicConfig(**kwargs):
filename = kwargs.pop("filename", None)
mode = kwargs.pop("filemode", 'a')
if filename:
h = FileHandler(filename, mode)
h = FileHandler(filename, mode, encoding=encoding)
else:
stream = kwargs.pop("stream", None)
h = StreamHandler(stream)
Expand Down
23 changes: 21 additions & 2 deletions Lib/test/test_logging.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2001-2017 by Vinay Sajip. All Rights Reserved.
# Copyright 2001-2019 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
Expand All @@ -16,7 +16,7 @@

"""Test harness for the logging module. Run all tests.

Copyright (C) 2001-2017 Vinay Sajip. All Rights Reserved.
Copyright (C) 2001-2019 Vinay Sajip. All Rights Reserved.
"""

import logging
Expand Down Expand Up @@ -4445,6 +4445,25 @@ def test_force(self):
self.assertEqual(new_string_io.getvalue().strip(),
'WARNING:root:warn\nINFO:root:info')

def test_encoding(self):
try:
encoding = 'utf-8'
logging.basicConfig(filename='test.log', encoding=encoding,
format='%(message)s', level=logging.DEBUG)

self.assertEqual(len(logging.root.handlers), 1)
handler = logging.root.handlers[0]
self.assertIsInstance(handler, logging.FileHandler)
self.assertEqual(handler.encoding, encoding)
logging.debug('The Øresund Bridge joins Copenhagen to Malmö')
finally:
handler.close()
with open('test.log', encoding='utf-8') as f:
data = f.read().strip()
os.remove('test.log')
self.assertEqual(data,
'The Øresund Bridge joins Copenhagen to Malmö')

def _test_log(self, method, level=None):
# logging.root has no handlers so basicConfig should be called
called = []
Expand Down