As Guido states in the story of None, True and False, context matters in the case of not making True and False keywords in the first place. When bool was introduced (with PEP 285 in Python 2.3) it couldn't of been made a keyword because a lot of code in existence already defined it in one way or another:
The situation for True/False is a little different. They weren't always part of the language, and many people had invented their own convention. People would define constants named true and false, True and False, or TRUE and FALSE, and use those consistently throughout their code. I don't recall which spelling was most popular, but when we introduced True and False into the language, we definitely did not want to break any packages that were defining their own True and False constants.
and continues to state in a later paragraph:
So, essentially our hand was forced in this case, and we had to introduce True and False as built-in constants, not as keywords. But over time, code defining its own versions of True and False (by whichever name) became more and more frowned upon, and by the time Python 3 came around, when we looked at opportunities for cleaning up the language, we found that it was logical to make True and False keywords, by analogy to None.
You correctly assume that:
The only reason I can think of is compatibility with existing code base.
And, indeed, this is the case. The need to keep backwards-compatibility between versions of Python 2 is why True and False aren't keywords there.
Python 3 is different in that it introduced a number of backwards incompatible changes in an effort to clean the language up, the awkward re-assigning to True and False can no longer be done, thankfully.