unicodedata en Python: normaliza Unicode

Publicado el: 11/08/2026
Tempo de leitura: 5 minutos
Alfabeto tridimensional que representa normalización Unicode con unicodedata en Python

El módulo unicodedata permite acceder a la base oficial de caracteres Unicode integrada en la versión de Python en ejecución. Una aplicación puede consultar nombres, categorías, valores numéricos, clases bidireccionales, marcas combinantes, descomposiciones y formas normalizadas. Estas funciones son esenciales en búsquedas, importación de datos, identificadores, slugs, comparaciones, validación e internacionalización.

Esta guía explica las APIs principales y muestra cómo normalizar sin destruir información. Python 3.14.6 documenta la Unicode Character Database 16.0.0.

Consultar la versión Unicode

import unicodedata

print(unicodedata.unidata_version)

La versión puede cambiar nombres, categorías y caracteres reconocidos. Los sistemas que guardan claves normalizadas deben registrar la versión de Python y probar las actualizaciones.

Obtener el nombre de un carácter

name() devuelve el nombre oficial. Algunos caracteres no tienen nombre asignado, por lo que conviene proporcionar un valor por defecto.

print(unicodedata.name("½"))
print(unicodedata.name("\uFFFF", "SIN NOMBRE"))

Los nombres sirven para diagnóstico e informes. Son identificadores estandarizados, no traducciones para el usuario.

Buscar por nombre

lookup() realiza la operación inversa y genera KeyError si el nombre no existe.

caracter = unicodedata.lookup("LEFT CURLY BRACKET")
print(caracter)

También admite aliases y secuencias nombradas incluidas en la base. Valida nombres de usuarios y trata el error.

Categoría general

category() devuelve un código de dos letras. La primera indica un grupo amplio, como letras, marcas, números, puntuación, símbolos, separadores, controles o caracteres no asignados.

for caracter in ["A", "a", "9", "!", " "]:
    print(caracter, unicodedata.category(caracter))

Ejemplos: Lu para mayúscula, Ll para minúscula, Nd para dígito decimal y Zs para separador de espacio. Las categorías no son una política completa de seguridad.

decimal, digit y numeric

Unicode distingue varios conceptos numéricos. decimal() trata dígitos decimales, digit() incluye otras formas y numeric() cubre fracciones y numerales.

print(unicodedata.decimal("٩"))
print(unicodedata.digit("⁹"))
print(unicodedata.numeric("½"))

Define si un campo acepta solo ASCII, dígitos decimales internacionales o cualquier carácter numérico Unicode.

Marcas combinantes

combining() devuelve la clase combinante canónica. Cero suele indicar que no existe una clase combinante definida.

texto = "a\u0301"
for c in texto:
    print(repr(c), unicodedata.name(c), unicodedata.combining(c))

La secuencia contiene una letra y un acento separado. Puede verse igual que á aunque tenga longitud y bytes distintos.

Por qué normalizar

Unicode permite representaciones canónicamente equivalentes. Sin normalización, comparaciones, claves de base, cachés e índices pueden tratar textos visualmente iguales como distintos.

a = "café"
b = "cafe\u0301"
print(a == b)
print(unicodedata.normalize("NFC", a) == unicodedata.normalize("NFC", b))

Normalizar no resuelve diferencias de caja, puntuación, idioma ni caracteres visualmente confundibles.

NFC y NFD

NFD aplica descomposición canónica. NFC descompone y luego recompone cuando existe una forma precompuesta.

nfd = unicodedata.normalize("NFD", "acción")
nfc = unicodedata.normalize("NFC", nfd)

NFC es una opción común para guardar y comparar texto humano. NFD resulta útil para analizar marcas o crear una clave auxiliar sin acentos.

NFKC y NFKD

Las formas de compatibilidad pueden sustituir variantes estilísticas o históricas por equivalentes simples.

print(unicodedata.normalize("NFKC", "Ⅳ"))
print(unicodedata.normalize("NFKC", "Full"))

Estas transformaciones pueden perder distinciones. Úsalas en búsqueda o identificadores solo con una política definida. No las apliques ciegamente a contraseñas, firmas, documentos legales o contenido tipográfico.

Comprobar la forma

is_normalized() comprueba NFC, NFD, NFKC o NFKD.

texto = "café"
if not unicodedata.is_normalized("NFC", texto):
    texto = unicodedata.normalize("NFC", texto)

Normalizar directamente suele ser suficiente; la verificación ayuda en auditorías y métricas.

Quitar acentos con cuidado

Un patrón habitual descompone y elimina marcas sin espaciado. No es una transliteración universal.

def sin_acentos(texto):
    descompuesto = unicodedata.normalize("NFD", texto)
    filtrado = "".join(
        c for c in descompuesto
        if unicodedata.category(c) != "Mn"
    )
    return unicodedata.normalize("NFC", filtrado)

Usa el resultado como clave auxiliar, no como reemplazo del original. Muchas letras no se convierten correctamente así.

Descomposición

decomposition() devuelve puntos de código hexadecimales y a veces una etiqueta de compatibilidad.

print(unicodedata.decomposition("Ã"))
print(unicodedata.decomposition("①"))

Es útil para diagnóstico. Para transformar texto normalmente se debe usar normalize().

Texto bidireccional

bidirectional() devuelve la clase bidi y mirrored() identifica símbolos que pueden reflejarse en texto de derecha a izquierda.

print(unicodedata.bidirectional("٧"))
print(unicodedata.mirrored(">"))

Estas propiedades no sustituyen un motor de layout. Controles bidireccionales pueden ocultar el orden visual en código, logs y archivos; las herramientas de seguridad deben ofrecer vistas escapadas.

Ancho asiático

east_asian_width() clasifica caracteres como estrechos, anchos, fullwidth, halfwidth, ambiguos o neutros.

for c in "A界F":
    print(c, unicodedata.east_asian_width(c))

La propiedad ayuda, pero no calcula por sí sola el ancho final de terminal. Marcas, emojis y configuración siguen influyendo.

Casefold y normalización

Para comparación sin caja, normaliza y usa casefold().

def clave_busqueda(texto):
    return unicodedata.normalize("NFKC", texto).casefold()

print(clave_busqueda("Straße") == clave_busqueda("STRASSE"))

Conserva siempre el original y no uses una clave simplificada como prueba de identidad.

Caracteres confundibles

La normalización no une todos los caracteres visualmente similares. Letras latinas, griegas y cirílicas pueden parecer iguales y seguir siendo distintas. Los homógrafos afectan usuarios, dominios, paquetes e identificadores.

Usa restricciones de scripts, detección especializada y revisión humana en contextos sensibles.

Preparar una clave de búsqueda

def preparar_busqueda(texto):
    texto = unicodedata.normalize("NFKC", texto)
    texto = texto.casefold()
    return " ".join(texto.split())

Versiona esta función como parte del esquema del índice, porque una actualización Unicode puede cambiar resultados.

Errores frecuentes

  • Comparar texto sin una forma normalizada.
  • Usar NFKC donde importa conservar distinciones.
  • Reemplazar el original por una copia sin acentos.
  • Tratar cualquier número Unicode como dígito ASCII.
  • Esperar que normalizar evite homógrafos.
  • Usar ancho asiático como cálculo visual completo.
  • Ignorar la versión Unicode.

Buenas prácticas

  • Conserva siempre la entrada original.
  • Define normalización por campo y finalidad.
  • Normaliza ambos lados de la comparación.
  • Versiona claves e índices derivados.
  • Prueba idiomas y scripts relevantes.
  • Usa casefold() para comparación caseless.
  • Aplica controles extra en identificadores sensibles.

Guías relacionadas

Continúa con textwrap en Python, locale en Python, fnmatch en Python, pydoc en Python y linecache en Python.

Consulta la documentación oficial de unicodedata y el Unicode HOWTO.

Conclusión

unicodedata permite tratar texto internacional con reglas explícitas y reproducibles. La normalización mejora búsquedas y comparaciones, pero no sustituye políticas de idioma, identidad, seguridad o presentación. Conserva el original y elige cada transformación según el dominio.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Red de servidores que representa la gestión de recursos con ExitStack en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    ExitStack en Python: gestiona recursos

    Aprende ExitStack en Python para gestionar archivos, conexiones, callbacks y limpieza dinámica con seguridad y orden predecible.

    Ler mais

    Tempo de leitura: 6 minutos
    11/08/2026
    Carpeta con candado que representa tipos y permisos con stat en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    stat en Python: tipos y permisos

    Aprende stat en Python para interpretar tipos de archivo, permisos, enlaces, timestamps, atributos de Windows y flags de Unix con

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Portátil con código que representa documentación automática con pydoc en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pydoc en Python: documentación automática

    Aprende pydoc en Python para generar ayuda en terminal, HTML, búsqueda y un servidor local de documentación de forma segura.

    Ler mais

    Tempo de leitura: 6 minutos
    10/08/2026
    Teclado internacional que representa números, moneda y fechas con locale en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    locale en Python: números, moneda y fechas

    Aprende locale en Python para formatear e interpretar números, moneda, fechas, encodings y orden cultural sin errores de concurrencia.

    Ler mais

    Tempo de leitura: 6 minutos
    09/08/2026
    Monitor y red que representan información del sistema con platform en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    platform en Python: información del sistema

    Aprende platform en Python para identificar sistema operativo, arquitectura, distribución, versión de Python y entorno de ejecución.

    Ler mais

    Tempo de leitura: 5 minutos
    09/08/2026
    Código y compilador que representan rutas y variables de build con sysconfig en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    sysconfig en Python: rutas y build

    Aprende sysconfig en Python para descubrir rutas de instalación, variables de build, headers, virtualenvs y plataformas de forma segura.

    Ler mais

    Tempo de leitura: 6 minutos
    09/08/2026