The problem is that the logger’s level is still set to the default. So the logger discards the message before it even gets to the handlers. The fact that the handler would have accepted the message if it received it doesn’t matter, because it never receives it.
So, just add this:
logger.setLevel(logging.INFO)
As the docs explain, the logger’s default level is NOTSET, which means it checks with its parent, which is the root, which has a default of WARNING.
And you can probably leave the handler at its default of NOTSET, which means it defers to the logger’s filtering.