Подтвердить что ты не робот

Python TypeError: строка непустого формата, переданная объекту.__ format__

Недавно я ударил это исключение TypeError, которое было очень сложно отладить. В конце концов я уменьшил его до этого небольшого теста:

>>> "{:20}".format(b"hi")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: non-empty format string passed to object.__format__

Это очень неочевидно, для меня в любом случае. Обходной путь для моего кода состоял в том, чтобы декодировать строку байтов в unicode:

 >>> "{:20}".format(b"hi".decode("ascii"))
 'hi                  '

В чем смысл этого исключения? Есть ли способ сделать это более понятным?

4b9b3361

Ответ 1

bytes объекты не имеют собственного метода __format__, поэтому используется значение по умолчанию от object:

>>> bytes.__format__ is object.__format__
True
>>> '{:20}'.format(object())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: non-empty format string passed to object.__format__

Это просто означает, что вы не можете использовать ничего, кроме прямого, неформатированного негласного форматирования на них. Явно конвертируем в строковый объект (как вы это сделали, расшифровывая bytes до str), чтобы получить поддержку спецификации формата.

Вы можете сделать преобразование явным с помощью преобразования строки !s:

>>> '{!s:20s}'.format(b"Hi")
"b'Hi'               "
>>> '{!s:20s}'.format(object())
'<object object at 0x1100b9080>'

object.__format__ явно отклоняет строки форматирования, чтобы избежать неявных преобразований строк, особенно потому, что инструкции форматирования специфичны по типу.

Ответ 2

Это также происходит при попытке форматирования None:

>>> '{:.0f}'.format(None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: non-empty format string passed to object.__format__

Это заняло некоторое время, чтобы сработать (в моем случае, когда None возвращалась переменной экземпляра)!