Biblioteca Python para validar, calcular y formatear el Rol Único Tributario (RUT) chileno. Sin dependencias externas, tipado estático completo, y soporte para procesamiento por lotes, streaming, CLI, e integraciones opcionales con Pydantic v2, FastAPI, pandas y polars.
from rutificador import Rut
rut = Rut("12.345.678-5")
print(rut.formatear(separador_miles=True)) # 12.345.678-5
resultado = Rut.parse("12.345.678-9")
print(resultado.estado, resultado.codigo_error) # invalido DV_DISCORDANTE- Características
- Instalación
- Uso básico
- Línea de comandos
- Procesamiento por lotes
- Integraciones
- Validación avanzada
- Referencia de errores
- Registro y depuración
- API de referencia
- Desarrollo
- Licencia
- Cero dependencias base — solo estándar de Python. Instalación liviana y segura.
- Validación completa — formato, dígito verificador, longitud configurable, modos de rigor.
- Formateo flexible — separador de miles, mayúsculas en DV, separador personalizado.
- Streaming y lotes — archivos de millones de líneas sin cargar todo en memoria.
- Procesamiento en paralelo — motor por procesos (CPU-bound) o hilos (I/O-bound).
- Parseo seguro —
Rut.parse()nunca lanza excepción, siempre retorna resultado estructurado. - Enmascaramiento y tokenización — protege datos sensibles en logs, exports o pantallas.
- Motor de sugerencias — corrección fuzzy de errores tipográficos comunes.
- Integraciones opcionales — Pydantic v2, FastAPI, pandas, polars.
- Tipado estático —
py.typed(PEP 561), cobertura mypy completa. - CLI profesional — salida en text, JSON, JSONL, CSV y XML.
pip install rutificadorCon extras:
pip install rutificador[pydantic] # Pydantic v2
pip install rutificador[fastapi] # FastAPI + Pydantic
pip install rutificador[pandas] # pandas accessor
pip install rutificador[polars] # polars namespace
pip install rutificador[full] # todo lo anteriorfrom rutificador import Rut
# Creación directa — valida en el constructor (lanza excepción si es inválido)
rut = Rut("12.345.678-5")
# Parseo seguro — nunca lanza excepción, siempre retorna resultado estructurado
resultado = Rut.parse("12.345.678-5")
print(resultado.estado) # valido
print(resultado.normalizado) # 12345678-5
resultado = Rut.parse("12.345.678-9")
print(resultado.estado) # invalido
print(resultado.codigo_error) # DV_DISCORDANTE
# Capturar error en validación directa
from rutificador.exceptions import ErrorValidacionRut
try:
Rut("12.345.678-9")
except ErrorValidacionRut as e:
print(e.codigo_error) # DV_DISCORDANTErut = Rut("12345678-5")
print(rut.formatear()) # 12345678-5
print(rut.formatear(separador_miles=True)) # 12.345.678-5
print(rut.formatear(mayusculas=True)) # 12345678-5
print(rut.formatear(separador_miles=True, mayusculas=True)) # 12.345.678-5
# Con DV en 'k'
rut_k = Rut("12345670-k")
print(rut_k.formatear(separador_miles=True, mayusculas=True)) # 12.345.670-Kfrom rutificador import calcular_digito_verificador
dv = calcular_digito_verificador("12345678")
print(dv) # 5from rutificador import Rut
# Ofuscar parcialmente
print(Rut.enmascarar("12.345.678-5", mantener=3, caracter="X")) # XXXXX678-5
print(Rut.enmascarar("12.345.678-5", mantener=4)) # ****5678-5
# Tokenización
print(Rut.enmascarar("12.345.678-5", modo="token", clave="mi-clave")) # tok_abc123...from rutificador import Rut
# Sugerir correcciones para un RUT con error tipográfico
sugerencias = Rut.sugerir("12.345.687-5")
print(sugerencias) # ['12345678-5', ...]
# Autocorrección inteligente
mejor_opcion = Rut.mejorar("12a345678-k")
print(mejor_opcion) # 12345678-5# Validar desde un archivo
rutificador validar ruts.txt
# Validar desde stdin
cat ruts.txt | rutificador validar
# Formatear con separador de miles
rutificador formatear ruts.txt --separador-miles --mayusculas
# Enmascarar datos sensibles
rutificador enmascarar ruts.txt --mantener 3
# Salida estructurada
rutificador validar ruts.txt --format jsonl > resultados.jsonl
# Procesamiento paralelo
rutificador validar ruts_pesados.txt --paralelo --format csv
# Autocorreccion + sugerencias
rutificador validar sucia_db.txt --mejorar --sugerir
# Informacion del sistema
rutificador info| Comando | Descripción |
|---|---|
validar |
Valida RUTs desde archivo o stdin |
formatear |
Valida y formatea RUTs con opciones de salida |
enmascarar |
Ofusca/tokeniza RUTs para proteger datos sensibles |
info |
Muestra versión, entorno y funcionalidades |
| Formato | Descripción |
|---|---|
text |
Legible por humanos con resumen de auditoría en stderr |
json |
Array JSON estándar (OOM-Safe via streaming) |
jsonl |
Una línea por registro — ideal para Big Data |
csv |
Hoja de cálculo con cabecera |
xml |
Estructura incremental para integraciones legacy |
from rutificador import ProcesadorLotesRut
ruts = ['12.345.678-5', '98.765.432-1', '1-9']
procesador = ProcesadorLotesRut()
resultado = procesador.validar_lista_ruts(ruts)
print(len(resultado.detalles_validos)) # 2
print(len(resultado.detalles_invalidos)) # 1
# Formatear a JSON, CSV o XML
csv = procesador.formatear_lista_ruts(ruts, formato="csv")
print(csv)
# rut
# 12345678-5
# ...
# Paralelismo explícito
procesador = ProcesadorLotesRut(motor_paralelo="process")
resultado = procesador.validar_lista_ruts(ruts, paralelo=True)from rutificador import validar_flujo_ruts, formatear_flujo_ruts
# Validar millones de RUTs sin cargar todo en memoria
ruts = (linea.strip() for linea in open("muy_grande.txt"))
for es_valido, resultado in validar_flujo_ruts(ruts):
if es_valido:
print(resultado.valor)pip install rutificador[pydantic]from pydantic import BaseModel
from rutificador.contrib.pydantic import RutStr, rut_str_annotated
class Usuario(BaseModel):
rut: RutStr
u = Usuario(rut="12.345.678-5")
print(u.rut) # 12345678-5
# Formato específico
RutConPuntos = rut_str_annotated(formato="miles-con-guion")
class UsuarioV2(BaseModel):
rut: RutConPuntos
u2 = UsuarioV2(rut="12.345.678-5")
print(u2.rut) # 12.345.678-5pip install rutificador[fastapi]from fastapi import FastAPI, Depends
from rutificador import Rut
from rutificador.contrib.fastapi import parametro_rut
app = FastAPI()
@app.get("/usuario/{rut}")
def obtener_usuario(rut: Rut = Depends(parametro_rut)):
return {"rut_normalizado": str(rut), "dv": rut.digito_verificador}Los errores de validación retornan 422 Unprocessable Entity con código estructurado (DV_DISCORDANTE, CARACTERES_INVALIDOS, etc.).
pip install rutificador[pandas]import pandas as pd
import rutificador.pandas # activa el accessor .rut
s = pd.Series(["12.345.678-5", "12.345.678-9", "invalid"])
print(s.rut.es_valido())
# 0 True
# 1 False
# 2 False
print(s.rut.formatear(formato="miles"))
# 0 12.345.678-5
# 1 None
# 2 Nonepip install rutificador[polars]import polars as pl
import rutificador.polars # activa el namespace .rut
df = pl.DataFrame({"rut": ["12.345.678-5", "12.345.678-9", "invalid"]})
print(df.with_columns(pl.col("rut").rut.es_valido()))from rutificador import Rut, ValidadorRut
from rutificador.config import RigorValidacion, ConfiguracionRut
# Modo flexible: tolera espacios, guiones extra, etc.
validador = ValidadorRut(modo=RigorValidacion.FLEXIBLE)
rut = Rut('12 345 678-5', validador=validador)
# Configuración avanzada
config = ConfiguracionRut(max_digitos=10)
validador = ValidadorRut(configuracion=config)
# Normalización con rigor flexible
normalizado, errores, advertencias = Rut.normalizar(
"12 345 678-5", modo=RigorValidacion.FLEXIBLE
)
print(normalizado) # 12345678-5Todos los errores tienen códigos estables y severidad explícita:
from rutificador import Rut
res = Rut.parse("12..345")
for err in res.errores:
print(err.codigo, err.severidad, err.hint)| Código | Descripción |
|---|---|
ERROR_TIPO |
Tipo inválido |
RUT_VACIO |
Entrada vacía |
CARACTERES_INVALIDOS |
Caracteres no permitidos |
FORMATO_PUNTOS |
Separadores de miles inválidos |
FORMATO_GUION |
Guión inválido |
LONGITUD_MINIMA |
Longitud mínima no alcanzada |
LONGITUD_MAXIMA |
Longitud máxima excedida |
DV_INVALIDO |
Dígito verificador inválido |
DV_DISCORDANTE |
DV no coincide |
ESTADO_ENMASCARADO |
Enmascarado en estado no válido |
CLAVE_TOKEN_REQUERIDA |
Falta clave de tokenización |
| Código | Descripción |
|---|---|
NORMALIZACION_ESPACIOS |
Espacios eliminados |
NORMALIZACION_GUION |
Guión normalizado |
NORMALIZACION_PUNTOS |
Puntos eliminados |
NORMALIZACION_DV |
DV en minúscula |
CEROS_IZQUIERDA |
Ceros a la izquierda eliminados |
import logging
from rutificador import configurar_registro
configurar_registro(level=logging.DEBUG)Con handler personalizado:
import logging
import json
from rutificador import configurar_registro
class JsonFormatter(logging.Formatter):
def format(self, record):
return json.dumps({"nivel": record.levelname, "mensaje": record.getMessage()})
handler = logging.StreamHandler()
handler.setFormatter(JsonFormatter())
configurar_registro(level=logging.INFO, handler=handler)from rutificador import ProcesadorLotesRut
procesador = ProcesadorLotesRut()
resultado = procesador.validar_lista_ruts(["12.345.678-5"], paralelo=False)
detalle = resultado.detalles_validos[0]
print(detalle.valor) # 12345678-5
print(detalle.validador_modo) # estricto/flexible
print(detalle.duracion) # segundos consumidos en la validacion
# Errores con codigo estructurado
resultado_error = procesador.validar_lista_ruts(["12345678-9"])
problema = resultado_error.ruts_invalidos[0]
print(problema.rut, problema.codigo, problema.mensaje)from rutificador import evaluar_rendimiento
resultados = evaluar_rendimiento(num_ruts=1000)
print(resultados['tasa_exito'])from rutificador.formatter import FormateadorRut, FabricaFormateadorRut
class FormateadorLista(FormateadorRut):
def formatear(self, ruts):
return ','.join(ruts)
FabricaFormateadorRut.registrar_formateador('lista', FormateadorLista)git clone https://github.com/cortega26/rutificador.git
cd rutificador
python -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txt
pip install -e .
pre-commit installpytest -W error::DeprecationWarning # Tests sin deprecaciones
mypy rutificador/ # Tipado estatico
ruff check . # Lint
ruff format . --check # Formato
bandit -r rutificador/ # SeguridadLas contribuciones son bienvenidas. Revisa CONTRIBUTING.md para las directrices completas.
Rutificador no verifica la existencia del RUT en registros oficiales ni realiza enriquecimiento de identidad. Su alcance es la validación sintáctica, normalización y formateo según las reglas locales del RUT chileno.
MIT © Carlos Ortega González. Ver LICENSE.
Este proyecto se inspiró en rut-chile de gevalenz.
Built and maintained by Carlos Ortega — automation, data systems, and web technical hygiene consulting. Portfolio and services: tooltician.com.