homepage

This issue tracker has been migrated to GitHub , and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: json.dumps() lacks information about RecursionError related to default function
Type: enhancement Stage:
Components: Library (Lib) Versions: Python 3.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Krzysztof Nazarewski, bob.ippolito, ezio.melotti, rhettinger, serhiy.storchaka
Priority: normal Keywords:

Created on 2017年06月22日 09:38 by Krzysztof Nazarewski, last changed 2022年04月11日 14:58 by admin.

Pull Requests
URL Status Linked Edit
PR 2856 closed svelankar, 2017年07月25日 02:07
PR 2857 open svelankar, 2017年07月25日 02:30
Messages (2)
msg296620 - (view) Author: Krzysztof Nazarewski (Krzysztof Nazarewski) Date: 2017年06月22日 09:38
RecursionErrors related to json.dumps' default argument give no information whatsoever about the underlying issue.
Example:
$ /usr/bin/python3 -c "import json;from decimal import Decimal;json.dumps(Decimal(),default=lambda v:round(v, 8))"
Traceback (most recent call last):
 File "<string>", line 1, in <module>
 File "/usr/lib/python3.6/json/__init__.py", line 238, in dumps
 **kw).encode(obj)
 File "/usr/lib/python3.6/json/encoder.py", line 199, in encode
 chunks = self.iterencode(o, _one_shot=True)
 File "/usr/lib/python3.6/json/encoder.py", line 257, in iterencode
 return _iterencode(o, 0)
 File "<string>", line 1, in <lambda>
 File "/usr/lib/python3.6/_pydecimal.py", line 1919, in __round__
 return self.quantize(exp)
 File "/usr/lib/python3.6/_pydecimal.py", line 2603, in quantize
 return ans._fix(context)
 File "/usr/lib/python3.6/_pydecimal.py", line 1720, in _fix
 if not self:
 File "/usr/lib/python3.6/_pydecimal.py", line 852, in __bool__
 return self._is_special or self._int != '0'
RecursionError: maximum recursion depth exceeded in comparison
Details:
I have encountered issue when porting my code from Python 2 to 3.
Traceback shows depth of 6, but says recursion was already reached.
My first idea was that recursion counter was messed up, but it was not the case.
Recursion limit was indeed reached because round() in Python 3 is returning Decimal and then applies default infinitely.
The part of recursing code was inside C so it was not displayed in the traceback.
Summing up it took me over 2 hours to determine what was wrong with the code.
Fix ideas:
- do not call default more than once on the same root object (might be problematic to implement)
- raise an error if new object is equal to the previous (partially resolving issue since custom objects might not implement equality operator)
- add a flag to raise an error when new object's class is equal to the previous (might give false positives hence the flag)
msg299561 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017年07月31日 15:08
simplejson behaves the same.
I thought default() was allowed to return only instances of types directly supported by JSON encoder (type(None), bool, int, float, list, tuple, dict). Is there a reason of allowing to call default() more than once on the same root object?
History
Date User Action Args
2022年04月11日 14:58:48adminsetgithub: 74917
2017年07月31日 15:08:28serhiy.storchakasetnosy: + rhettinger, ezio.melotti, serhiy.storchaka, bob.ippolito

messages: + msg299561
versions: - Python 3.3, Python 3.4, Python 3.5, Python 3.6
2017年07月25日 02:30:26svelankarsetpull_requests: + pull_request2908
2017年07月25日 02:07:40svelankarsetpull_requests: + pull_request2907
2017年06月22日 09:41:31Krzysztof Nazarewskisettitle: json.dumps() lack of information about RecursionError when using default function -> json.dumps() lacks information about RecursionError related to default function
2017年06月22日 09:38:57Krzysztof Nazarewskicreate

AltStyle によって変換されたページ (->オリジナル) /