locale en Python: números, moneda y fechas

Publicado el: 09/08/2026
Tempo de leitura: 6 minutos
Teclado internacional que representa números, moneda y fechas con locale en Python

Los usuarios de distintos países esperan separadores decimales, símbolos de moneda, nombres de meses y reglas de ordenación acordes con su cultura. locale en Python permite acceder a la base POSIX del sistema operativo para formatear e interpretar esos valores.

La funcionalidad exige cuidado porque el locale es una propiedad global del proceso heredada de la biblioteca C. Cambiarlo afecta a otras partes de la aplicación y no es thread-safe en la mayoría de sistemas. Esta guía explica configuración inicial, categorías, números, moneda, fechas, collation, encodings, fallos de despliegue y alternativas para servidores concurrentes.

El contenido complementa nuestras guías sobre Decimal, zoneinfo, statistics, platform y sysconfig.

Qué representa un locale

Un locale reúne convenciones culturales instaladas en el sistema: separador decimal, agrupación de miles, símbolo monetario, posición del signo, nombres de meses y días, formatos de fecha y reglas de ordenación.

Los nombres disponibles dependen de la plataforma y de los datos instalados. Un locale presente en desarrollo puede faltar en un container de producción.

Estado inicial del proceso

Los programas C suelen empezar en el locale portátil C. Python configura aspectos de LC_CTYPE durante el arranque para establecer el encoding, pero las otras categorías conservan el comportamiento portátil hasta que la aplicación pide las preferencias del usuario.

import locale

locale.setlocale(locale.LC_ALL, "")

La string vacía solicita la configuración predeterminada del usuario, normalmente definida por variables de entorno.

Consultar sin cambiar

actual = locale.setlocale(locale.LC_ALL)
print(actual)

Si se omite el segundo argumento, setlocale() devuelve el estado actual. Guardar y restaurar sigue siendo peligroso si otras threads trabajan entre ambas llamadas.

setlocale no es thread-safe

La configuración es global. Una thread puede cambiar la coma decimal mientras otra genera una factura.

Configura el locale una sola vez al inicio de una herramienta de escritorio o línea de comandos. Un servidor para usuarios de culturas diferentes debe utilizar objetos de formato independientes por petición.

Categorías

  • LC_NUMERIC: números.
  • LC_MONETARY: moneda.
  • LC_TIME: fechas y horas.
  • LC_COLLATE: ordenación de strings.
  • LC_CTYPE: entorno de caracteres y encoding.
  • LC_MESSAGES: mensajes del sistema en POSIX.
  • LC_ALL: todas las categorías.

Cambiar una sola categoría reduce efectos, pero el estado sigue siendo global.

Locale no disponible

try:
    locale.setlocale(locale.LC_ALL, "es_ES.UTF-8")
except locale.Error:
    locale.setlocale(locale.LC_ALL, "")

No supongas que el mismo nombre funciona en Windows, Linux y macOS. Instala los datos durante el deploy o define un fallback explícito.

Normalizar nombres

normalizado = locale.normalize("es_ES.UTF-8")

La función aplica aliases, pero no instala el locale. Puede devolver el nombre original si no logra adaptarlo.

Convenciones numéricas y monetarias

convenciones = locale.localeconv()
print(convenciones["decimal_point"])
print(convenciones["thousands_sep"])
print(convenciones["currency_symbol"])

El diccionario también informa agrupación, casas decimales monetarias, posición del símbolo y signos. Algunos campos pueden usar CHAR_MAX para indicar que no están definidos.

Formatear números

texto = locale.format_string(
    "%.2f",
    1234567.89,
    grouping=True,
)

La función usa LC_NUMERIC y la sintaxis del operador %.

Localizar una representación normalizada

localizado = locale.localize(
    "1234567.89",
    grouping=True,
)

localize(), disponible desde Python 3.10, aplica separadores culturales a una string numérica normalizada.

Interpretar números localizados

valor = locale.atof("1.234,56")

El ejemplo depende de un locale con punto para miles y coma decimal. atof() usa delocalize() y luego float.

Para dinero, pasa Decimal.

from decimal import Decimal

importe = locale.atof("1.234,56", func=Decimal)

Interpretar enteros

cantidad = locale.atoi("1.234")

Valida límites y rechaza formatos ambiguos. Un texto de otra cultura puede ser interpretado mal sin generar excepción.

delocalize

normalizado = locale.delocalize("1.234,56")

La función elimina agrupación y adapta el separador decimal. No valida precisión, signo permitido ni reglas de negocio.

Formatear moneda

texto = locale.currency(
    1234.50,
    symbol=True,
    grouping=True,
)

currency() no funciona con el locale C. Configura una categoría monetaria válida.

Un símbolo como $ es ambiguo. Guarda siempre el código ISO de moneda como dato separado y considera international=True.

Locale no decide la moneda

El locale indica presentación, no qué moneda representa el número. Un usuario español puede consultar una factura en dólares. Mantén importe y código monetario explícitos.

Fechas y horas

strftime() usa LC_TIME para nombres y formatos.

from datetime import datetime

texto = datetime.now().strftime("%A, %d de %B de %Y")

Locale no es timezone. Convierte el instante con zoneinfo antes de formatear.

Información del sistema

En plataformas compatibles, nl_langinfo() devuelve formatos de fecha, nombres, encoding y separadores.

if hasattr(locale, "nl_langinfo"):
    formato = locale.nl_langinfo(locale.D_FMT)

Las constantes disponibles varían. Prueba el entorno real.

Ordenación cultural

palabras = ["ábaco", "acción", "zebra"]
ordenadas = sorted(palabras, key=locale.strxfrm)

strxfrm() crea claves adecuadas para comparaciones repetidas con el LC_COLLATE actual.

strcoll

resultado = locale.strcoll("fan", "fútbol")

Un valor negativo, cero o positivo indica orden. Depende del locale activo.

Ordenación no es identidad

Dos strings cercanas en collation no son necesariamente iguales para login, claves o deduplicación. Define reglas Unicode y de dominio separadas.

Encoding preferido

encoding = locale.getpreferredencoding(False)

La función estima el encoding preferido. En modo UTF-8 de Python y Android devuelve UTF-8.

Para archivos y protocolos nuevos, declara UTF-8 de forma explícita.

getencoding

Desde Python 3.11, getencoding() devuelve el encoding del locale actual ignorando el modo UTF-8.

encoding_actual = locale.getencoding()

getlocale

idioma, encoding = locale.getlocale(locale.LC_NUMERIC)

El locale C se representa como (None, None). LC_ALL no es válido para esta función.

Variables de entorno

En POSIX, LC_ALL, las variables por categoría y LANG influyen. Los containers suelen fallar cuando declaran un locale no instalado.

Usa imágenes con UTF-8 y prueba exactamente el entorno del deploy.

C y C.UTF-8

C es portátil y determinista. C.UTF-8 es común en Linux, pero no universal.

Python incluye coerción de locale y modo UTF-8 para reducir fallos de encoding.

Las bibliotecas no deben cambiarlo

Una biblioteca reutilizable desconoce qué threads comparten el proceso. Llamar setlocale() dentro de una función pública crea un efecto global inesperado.

Recibe valores normalizados o permite que el llamador proporcione el formatter.

Servidores web

No cambies el locale por petición. Dos peticiones simultáneas pueden mezclar comas, puntos, monedas y meses.

Usa bibliotecas con objetos de locale independientes, como Babel, o formatters deterministas con configuración explícita.

gettext

Locale gestiona convenciones, no la traducción completa de mensajes. Usa gettext para catálogos de la aplicación.

Pruebas

Comprueba solamente locales instalados y salta los ausentes de forma explícita. No cambies locale global en paralelo.

def intentar_locale(nombre):
    try:
        locale.setlocale(locale.LC_ALL, nombre)
    except locale.Error:
        return False
    return True

Usa procesos separados para probar varias culturas con fiabilidad.

Seguridad

Las strings localizadas siguen siendo entrada externa. Limita tamaño, valida caracteres y no uses el resultado directamente como SQL, comando o ruta.

La validez cultural no sustituye reglas de negocio. Importes negativos, infinitos o con demasiados decimales pueden estar prohibidos.

Errores frecuentes

  • Cambiar locale en cada petición.
  • Suponer que un nombre existe en todos los sistemas.
  • Usar float para dinero.
  • Confundir locale y timezone.
  • Confundir locale y moneda.
  • Comparar números localizados como strings.
  • Usar collation como igualdad.
  • Permitir que una biblioteca cambie el estado global.

Buenas prácticas

  • Configura una vez al inicio de programas simples.
  • Usa categorías específicas.
  • Trata locale.Error.
  • Usa Decimal para importes.
  • Mantén moneda y timezone explícitos.
  • Usa strxfrm() para ordenar.
  • Prefiere UTF-8 en formatos persistentes.
  • Usa formatters independientes en servidores.

Conclusión

locale en Python conecta la aplicación con convenciones culturales del sistema para números, moneda, fechas, encodings y ordenación.

Su principal límite es el estado global y no thread-safe. Funciona bien en herramientas locales configuradas una vez, mientras los servidores multiusuario deben usar formatters independientes. Consulta la documentación oficial de locale y Unicode CLDR.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    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
    Disco duro que representa archivos mapeados en memoria con mmap en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    mmap en Python: archivos en memoria

    Aprende mmap en Python para mapear archivos en memoria, buscar bytes, compartir datos y elegir lectura, escritura o copy-on-write.

    Ler mais

    Tempo de leitura: 6 minutos
    09/08/2026
    Código fuente que representa tokens y constantes del parser con el módulo token en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    token en Python: constantes del parser

    Aprende token en Python para interpretar tipos léxicos, operadores exactos, indentación, f-strings, t-strings y parsers por versión.

    Ler mais

    Tempo de leitura: 7 minutos
    07/08/2026
    Código fuente que representa palabras reservadas y soft keywords en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    keyword en Python: palabras reservadas

    Aprende keyword en Python para validar identificadores, palabras reservadas y soft keywords según la versión del intérprete.

    Ler mais

    Tempo de leitura: 7 minutos
    07/08/2026
    Arquitectura de software que representa clases abstractas con abc en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    abc en Python: clases abstractas

    Aprende abc en Python para crear clases abstractas, métodos obligatorios, subclasses virtuales y contratos estables.

    Ler mais

    Tempo de leitura: 5 minutos
    06/08/2026