Why does ord() fail when porting from Python 2 to Python 3?

岁酱吖の 提交于 2020-05-29 10:36:26

问题


I am trying to port a Python library called heroprotocol from Python 2 to Python 3. This library is used to parse replay files from an online game called Heroes of the Storm, for the purpose of getting data from the file (i.e. who played against who, when did they die, when did the game end, who won, etc).

It seems that this library was created for Python 2, and since I am using Python 3 (specifically Anaconda, Jupyter notebook) I would like to convert it to Python 3.

The specific issue I am having is that when I run

header = protocol.decode_replay_header(mpq.header['user_data_header']['content'])

which should get some basic data about the replay file, I get this error:

TypeError: ord() expected string of length 1, but int found

I googled the ord() function and found a few posts about the usage of ord() in Python 3, but none of them solved the issue I am having. I also tried posting in the "Issues" section on Github, but I got no response yet.

Why am I seeing this error?


回答1:


According to the issue you raised, the exception occurs on line 69 of decoders.py:

self._next = ord(self._data[self._used])

The obvious reason this would succeed in Python 2 but fail in Python 3 is that self._data is a bytestring. In Python 2, bytestrings are the "standard" string objects, so that indexing into one returns the character at that position (itself a string) …

# Python 2.7
>>> b'whatever'[3]
't'

… and calling ord() on the result behaves as expected:

>>> ord(b'whatever'[3])
116

However, in Python 3, everything is different: the standard string object is a Unicode string, and bytestrings are instead sequences of integers. Because of this, indexing into a bytestring returns the relevant integer directly …

# Python 3.6
>>> b'whatever'[3]
116

… so calling ord() on that integer makes no sense:

>>> ord(b'whatever'[3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: ord() expected string of length 1, but int found

So, you ought to be able to prevent the specific exception you're asking about here by simply removing the call to ord() on that and similar lines:

self._next = self._data[self._used]

… although of course it's likely that further problems (out of scope for this question) will be revealed as a result.



来源:https://stackoverflow.com/questions/47260954/why-does-ord-fail-when-porting-from-python-2-to-python-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!