The reason for why the whole unicode checking is done in python3 is to guarantee Unicode support in python3. I actually disliked the old half-string-half-binary approach and almost from the start enjoyed the clear distinction between str and bytes in python3.
That being said, the strings/bytes cleanup was also one of the few things that really broke backward compatibility with 2.x.
The convention with the Python C API is to return a non-NULL pointer to a python object on success, and return NULL and set the exception global variable on error. Yes, global variables are also alive and well.
That being said, the strings/bytes cleanup was also one of the few things that really broke backward compatibility with 2.x.