Skip to content

Commit 663b9dc

Browse files
fix: python2 UnicodeDecodeError
1 parent 99404b3 commit 663b9dc

File tree

4 files changed

+48
-6
lines changed

4 files changed

+48
-6
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Table of Contents
1919

2020
**jsonformatter** is a formatter for python output json log, you can easily output **LogStash** needed log format or other **custom** json format and you can easily **custom(add/replace)** `LogRecord` attribute.
2121

22-
**Python 2.7** and **python 3** are supported from version 0.2.0, if you are using a version lower than 0.2.0, **python 3** is only supported.
22+
**Python 2.7** and **python 3** are supported from version 0.2.X, if you are using a version lower than 0.2.X, **python 3** is only supported.
2323

2424

2525

jsonformatter/jsonformatter.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def usesTime(self):
3737
return self._fmt.find(self.asctime_search) >= 0
3838

3939
def format(self, record):
40-
return self._fmt % record.__dict__
40+
return str(self._fmt) % record.__dict__
4141

4242

4343
class StrFormatStyle(PercentStyle):
@@ -46,7 +46,7 @@ class StrFormatStyle(PercentStyle):
4646
asctime_search = '{asctime'
4747

4848
def format(self, record):
49-
return self._fmt.format(**record.__dict__)
49+
return str(self._fmt).format(**record.__dict__)
5050

5151

5252
class StringTemplateStyle(PercentStyle):
@@ -58,7 +58,7 @@ def __init__(self, fmt):
5858
PercentStyle.__init__(self, fmt)
5959
self._tpl = {}
6060
for _, v in fmt.items():
61-
self._tpl[v] = Template(v)
61+
self._tpl[v] = Template(str(v))
6262

6363
def usesTime(self):
6464
fmt = self._fmt
@@ -147,7 +147,7 @@ def checkRecordCustomAttrs(self, record_custom_attrs):
147147
else:
148148
return
149149

150-
def __init__(self, fmt=BASIC_FORMAT, datefmt=None, style='%', record_custom_attrs=None, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw):
150+
def __init__(self, fmt=BASIC_FORMAT, datefmt=None, style='%', record_custom_attrs=None, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding='utf-8', default=None, sort_keys=False, **kw):
151151
"""
152152
If ``record_custom_attrs`` is not ``None``, it must be a ``dict`` type, the key of dict will be setted as LogRecord's attribute, the value of key must be a callable object and without parameters, it returned obj will be setted as attribute's value of LogRecord.
153153
@@ -178,6 +178,8 @@ def __init__(self, fmt=BASIC_FORMAT, datefmt=None, style='%', record_custom_attr
178178
``(',', ': ')`` otherwise. To get the most compact JSON representation,
179179
you should specify ``(',', ':')`` to eliminate whitespace.
180180
181+
``encoding`` is the character encoding for str instances, only supported by python 2.7, default is UTF-8.
182+
181183
``default(obj)`` is a function that should return a serializable version
182184
of obj or raise TypeError. The default simply raises TypeError.
183185
@@ -191,6 +193,7 @@ def __init__(self, fmt=BASIC_FORMAT, datefmt=None, style='%', record_custom_attr
191193
"""
192194
# compatible python2 start
193195
if sys.version_info < (3, 0):
196+
kw.update(encoding=encoding)
194197
logging.Formatter.__init__(
195198
self, fmt='', datefmt=datefmt)
196199

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
setup(
1515
name='jsonformatter',
16-
version='0.2.1',
16+
version='0.2.2',
1717
description=(
1818
'Python log in json format.'
1919
),

test/test.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,45 @@ def test_template_style(self):
141141

142142
root.info("test %s style", 'template')
143143

144+
def test_percent_style_unicode(self):
145+
root = logging.getLogger()
146+
root.setLevel(logging.INFO)
147+
148+
formatter = JsonFormatter("""{"log":"%(message)s"}""", style="%")
149+
150+
sh = logging.StreamHandler()
151+
sh.setFormatter(formatter)
152+
sh.setLevel(logging.INFO)
153+
154+
root.addHandler(sh)
155+
root.info('test percent style unicode: %s', '中文')
156+
157+
def test_format_style_unicode(self):
158+
root = logging.getLogger()
159+
root.setLevel(logging.INFO)
160+
161+
formatter = JsonFormatter("""{"log":"{message}"}""", style="{")
162+
163+
sh = logging.StreamHandler()
164+
sh.setFormatter(formatter)
165+
sh.setLevel(logging.INFO)
166+
167+
root.addHandler(sh)
168+
root.info('test format style unicode: %s', '中文')
169+
170+
def test_template_style_unicode(self):
171+
root = logging.getLogger()
172+
root.setLevel(logging.INFO)
173+
174+
formatter = JsonFormatter("""{"log":"${message}"}""", style="$")
175+
176+
sh = logging.StreamHandler()
177+
sh.setFormatter(formatter)
178+
sh.setLevel(logging.INFO)
179+
180+
root.addHandler(sh)
181+
root.info('test template style unicode: %s', '中文')
182+
144183
def test_dict_format(self):
145184
DICT_FORMAT = {
146185
"name": "name",

0 commit comments

Comments
 (0)