Цей код неправильний, якщо ви не знаєте чогось, чого ми не знаємо:
if isinstance(data, bytes):
data = data.decode()
Ви (здається, не знаєте) кодування data. Ви припускаєте, що це UTF-8 , але це цілком може бути помилковим. Оскільки ви не знаєте кодування, у вас немає тексту . У вас є байти, які можуть мати будь-яке значення під сонцем.
Хороша новина полягає в тому, що більшість випадкових послідовностей байтів не є дійсними UTF-8, тому, коли це перерветься, він розіб’ється голосно ( errors='strict'за замовчуванням), а не мовчки робить неправильну справу. Ще кращою новиною є те, що більшість з тих випадкових послідовностей, які виявляються дійсними UTF-8, є також дійсними ASCII, які ( майже ) усі погоджуються щодо того, як все-таки проаналізувати.
Погана новина полягає в тому, що немає розумного способу це виправити. Існує стандартний спосіб надання інформації про кодування: використовувати strзамість bytes. Якщо якийсь сторонній код передав вам об’єкт bytesабо bytearrayоб’єкт без будь-якого подальшого контексту чи інформації, єдина правильна дія - це невдача.
Тепер, припускаючи, що ви знаєте кодування, ви можете використовувати functools.singledispatchтут:
@functools.singledispatch
def foo(data, other_arguments, ...):
raise TypeError('Unknown type: '+repr(type(data)))
@foo.register(str)
def _(data, other_arguments, ...):
@foo.register(bytes)
@foo.register(bytearray)
def _(data, other_arguments, ...):
data = data.decode('encoding')
return foo(data, other_arguments, ...)
Це не працює над методами, і це dataмає бути першим аргументом. Якщо ці обмеження не працюють для вас, використовуйте замість цього одну з інших відповідей.