Este código não está correto a menos que você saiba algo que não sabemos:
if isinstance(data, bytes):
data = data.decode()
Você não (parece) saber a codificação de data. Você está assumindo que é UTF-8 , mas isso pode muito bem estar errado. Como você não sabe a codificação, não tem texto . Você tem bytes, que podem ter algum significado sob o sol.
A boa notícia é que a maioria das sequências aleatórias de bytes não são UTF-8 válidas, portanto, quando isso for interrompido, será interrompido ruidosamente ( errors='strict'é o padrão) em vez de fazer silenciosamente a coisa errada. A notícia ainda melhor é que a maioria dessas sequências aleatórias que por acaso são UTF-8 válidas também são ASCII válidas, que ( quase ) todos concordam em como analisar de qualquer maneira.
A má notícia é que não existe uma maneira razoável de corrigir isso. Existe uma maneira padrão de fornecer informações de codificação: use em strvez de bytes. Se algum código de terceiros entregou a você um objeto bytesou bytearraysem qualquer contexto ou informação adicional, a única ação correta é falhar.
Agora, supondo que você conheça a codificação, você pode usar functools.singledispatchaqui:
@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, ...)
Isso não funciona em métodos e datadeve ser o primeiro argumento. Se essas restrições não funcionarem para você, use uma das outras respostas.