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





The line of your code that triggers the error is dataIO.save_json('data/local/changes.json', self.changes). What is self.changes?
– John Gordon
2 days ago


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.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

Opening a url is failing in Swift

Export result set on Dbeaver to CSV