Каждый handler имеет свой formatter.
Вы не сконфигурировали formatter для FileHandler('logger.log') поэтому он использует значение по умолчанию, которое не имеет никакого отношения к formatter, установленному для root.handlers внутри basicConfig().
Для отладки, полезно поставить logging_tree модуль, чтобы на дерево loggers посмотреть.
basicConfig() предназначен для простых скриптов, чтобы одним вызовом выполнить конфигурацию корневого logger. format параметр используется, чтобы сконфигурировать formatter у всех root.handlers.
В более сложных случаях, если вы хотите, чтобы дочерние loggers имели бы отличающуюся конфигурацию, то вместо basicConfig() следует использовать способы, которые могут сконфигурировать, не только root logger. Например, прочтите конфигурацию из файла:
logging.config.fileConfig('logging.conf')
Формат похож на ini файлы.
Если хочется прямо в коде конфигурацию указать (или в yaml/json формате из файла прочитать), можно словарь в logging.config.dictConfig() передать. Вот конфигурация для примера в вопросе (в YAML формате):
version: 1
formatters:
fmt:
format: "%(levelname)-8s [%(asctime)s] %(message)s"
handlers:
stream:
class: logging.StreamHandler
formatter: fmt
file:
class: logging.FileHandler
formatter: fmt
filename: logger.log
loggers:
"":
level: DEBUG
handlers: [stream]
logger:
handlers: [file]
Самая гибкая опция это руками в коде loggers, handlers и formatters создавать (getLogger(), .setLevel(), logging.StreamHandler(), , logging.Formatter(format), .setFormatter(), .addHandler()). Можно её использовать, если basicConfig, fileConfig, dictConfig не работают в вашем случае.