It's a mostly solved problem with Racket. What they probably should have done was have python 2 code somehow declare itself as python 2 (Racket does this with #lang at the top of files). Then, just have a python 2 compatibility layer that works in two steps. First step is to compile/parse it into a similar form as python 3. Additionally, provide a small python 2 runtime which provides different versions of the functions which changed from 2 to 3. I think the two steps are important because some stuff is easier to solve via compilation like "print" while other stuff may be only possible at runtime like strings being unicode.
You would still have some differences which can't be papered over, but it would have made writing code that works in both python 2 and 3 much easier.
You would still have some differences which can't be papered over, but it would have made writing code that works in both python 2 and 3 much easier.