Why am I getting “TypeError: unorderable types: str() < int()” in this code?
Why am I getting “TypeError: unorderable types: str() < int()” in this code?
@commands.command(pass_context=True)
@checks.serverowner()
async def change(self, ctx, change):
channel = self.bot.get_channel('432738903221469186')
change = ctx.message.clean_content[8:]
now = datetime.now()
count = len(self.changes.items()) + 1
self.changes[count] = {'date': now.strftime("%Y-%m-%d %H:%M:%S"), 'change': change}
dataIO.save_json('data/local/changes.json', self.changes)
await self.bot.send_message(channel, bold("N{SPARKLE} This change to the server was just made:") + box(change))
await self.bot.add_reaction(ctx.message, "N{WHITE HEAVY CHECK MARK}")
Here is changes.json:
{
"1" : {
"change" : "TEST",
"date" : "2018-06-29 01:07:37"
}
}
Here's the full error:
2|cdb_laun | Traceback (most recent call last):
2|cdb_laun | File "lib/discord/ext/commands/core.py", line 50, in wrapped
2|cdb_laun | ret = yield from coro(*args, **kwargs)
2|cdb_laun | File "/root/craig/cdbot/cogs/local.py", line 73, in change
2|cdb_laun | dataIO.save_json('data/local/changes.json', self.changes)
2|cdb_laun | File "/root/craig/cdbot/cogs/utils/dataIO.py", line 20, in save_json
2|cdb_laun | self._save_json(tmp_file, data)
2|cdb_laun | File "/root/craig/cdbot/cogs/utils/dataIO.py", line 50, in _save_json
2|cdb_laun | json.dump(data, f, indent=4, sort_keys=True, separators=(",", " : "))
2|cdb_laun | File "/usr/lib64/python3.5/json/__init__.py", line 178, in dump
2|cdb_laun | for chunk in iterable:
2|cdb_laun | File "/usr/lib64/python3.5/json/encoder.py", line 429, in _iterencode
2|cdb_laun | yield from _iterencode_dict(o, _current_indent_level)
2|cdb_laun | File "/usr/lib64/python3.5/json/encoder.py", line 352, in _iterencode_dict
2|cdb_laun | items = sorted(dct.items(), key=lambda kv: kv[0])
2|cdb_laun | TypeError: unorderable types: str() < int()
I apologize for the vague title and question, I've just dealt with handling JSON quite often and I'm not understanding the error here. I'm not even seeing where strings and integers are being compared.
My initial thought was that it had to do with count = len(self.changes.items()) + 1
but it doesn't.
count = len(self.changes.items()) + 1
dataIO.save_json('data/local/changes.json', self.changes)
self.changes
From the stack trace
dataIO.save_json('data/local/changes.json', self.changes)
is the problematic line from your code. What is the content of self.changes
?– aydow
2 days ago
dataIO.save_json('data/local/changes.json', self.changes)
self.changes
So the question is why is
json.dump()
calling sorted()
. The only reason I can think of is because of sort_keys=True
, and the keys of the dictionary contain a mix of strings and integers. This seems like a bug to me, it should probably convert the integers to strings before sorting, since JSON object keys are all strings.– Barmar
2 days ago
json.dump()
sorted()
sort_keys=True
It looks like you have a mixture of string & integer keys in your JSON dict, so the sorting breaks in Python 3.
– PM 2Ring
2 days ago
Looks like this bug: bugs.python.org/issue25457
– Barmar
2 days ago
2 Answers
2
Sorry, I figured this out. For some reason, during the first run it saved the JSON key as a string. In the second run, it saved it as an integer. self.changes
was printing as:
self.changes
{'2': {'date': '2018-06-29 02:02:03', 'change': 'TEST'}, '1': {'date': '2018-06-29 01:07:37', 'change': 'TEST'}}
To fix that, I just changed
self.changes[count] = {'date': now.strftime("%Y-%m-%d %H:%M:%S"), 'change': change}
to
self.changes[str(count)] = {'date': now.strftime("%Y-%m-%d %H:%M:%S"), 'change': change}
This is a bug in json.dump()
when you use sort_keys=True
and a dictionary has a mix of int
and string
keys.
json.dump()
sort_keys=True
int
string
You should either change self.changes
so that it uses a consistent type for the dictionary keys. Or don't use the sort_keys=True
option when calling json.dump()
from dataIO.save_json()
if you don't really need it.
self.changes
sort_keys=True
json.dump()
dataIO.save_json()
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
The line of your code that triggers the error is
dataIO.save_json('data/local/changes.json', self.changes)
. What isself.changes
?– John Gordon
2 days ago