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

    Programador analizando código para identificar tipos MIME de archivos con Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    mimetypes.guess_file_type: detecta tipos MIME

    Aprende mimetypes.guess_file_type en Python para detectar tipos MIME en rutas, URLs, uploads y respuestas HTTP con fallbacks seguros.

    Ler mais

    Tempo de leitura: 4 minutos
    13/09/2026
    Componentes de servidor que representan intérpretes Python aislados ejecutándose en paralelo
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    InterpreterPoolExecutor: paralelismo real en Python

    Aprende InterpreterPoolExecutor en Python para tareas CPU-bound, intérpretes aislados, paralelismo real y concurrencia segura.

    Ler mais

    Tempo de leitura: 6 minutos
    13/09/2026
    Microprocesador que representa las CPU disponibles para un proceso Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    os.process_cpu_count: cuenta CPUs disponibles

    Aprende os.process_cpu_count en Python para dimensionar workers según las CPU disponibles para el proceso.

    Ler mais

    Tempo de leitura: 4 minutos
    12/09/2026
    Portátil con código digital que representa datos BLOB en SQLite
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    sqlite3.Blob: lee BLOBs sin cargar todo en memoria

    Aprende sqlite3.Blob en Python para leer y escribir BLOBs por partes, reducir memoria y manejar datos binarios en SQLite.

    Ler mais

    Tempo de leitura: 5 minutos
    12/09/2026
    Análisis estadístico para random.binomialvariate en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    random.binomialvariate: simula resultados binomiales

    Aprende random.binomialvariate en Python para simular éxitos, validar probabilidades y analizar escenarios binomiales con ejemplos.

    Ler mais

    Tempo de leitura: 5 minutos
    11/09/2026
    Código Python y análisis de firmas de funciones
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    inspect.signature.bind: valida argumentos de funciones

    Aprende inspect.signature.bind en Python para validar argumentos, aplicar valores predeterminados y crear APIs dinámicas seguras.

    Ler mais

    Tempo de leitura: 5 minutos
    11/09/2026