123 lines
3.9 KiB
Python
123 lines
3.9 KiB
Python
# products_comands.py
|
|
# Uso:
|
|
# python .\products_comands.py .\Productos.csv .\comandos.txt
|
|
|
|
import csv, sys, os
|
|
|
|
TABLA = 'productos'
|
|
COLUMNAS = ['id_producto', 'nombre_comercial', 'categoria_general']
|
|
|
|
BLOQUE = 5000000
|
|
USAR_NULL = False # True => '' -> NULL
|
|
INSERT_POR_FILA = False # True => un INSERT por cada fila
|
|
|
|
def esc(s: str) -> str:
|
|
if s is None:
|
|
return "NULL" if USAR_NULL else "''"
|
|
s = str(s).strip().replace("'", "''")
|
|
if s == '':
|
|
return "NULL" if USAR_NULL else "''"
|
|
return f"'{s}'"
|
|
|
|
def es_encabezado(fila):
|
|
if not fila: return False
|
|
lowers = [c.lower().strip() for c in fila]
|
|
claves = ['id_producto', 'nombre_comercial', 'categoria_general', 'id', 'nombre', 'categoria']
|
|
return sum(any(k in c for k in claves) for c in lowers) >= 2
|
|
|
|
def leer_csv(ruta):
|
|
posibles = ['utf-8-sig', 'utf-8', 'cp1252', 'latin-1']
|
|
ultimo_error = None
|
|
for enc in posibles:
|
|
try:
|
|
with open(ruta, 'r', encoding=enc, newline='') as f:
|
|
muestra = f.read(4096); f.seek(0)
|
|
try:
|
|
dialect = csv.Sniffer().sniff(muestra, delimiters=",;\t|")
|
|
except Exception:
|
|
dialect = csv.excel_tab if '\t' in muestra else csv.excel
|
|
return list(csv.reader(f, dialect))
|
|
except UnicodeDecodeError as e:
|
|
ultimo_error = e
|
|
continue
|
|
|
|
try:
|
|
import chardet
|
|
with open(ruta, 'rb') as fb:
|
|
raw = fb.read()
|
|
enc = (chardet.detect(raw).get('encoding') or 'latin-1')
|
|
with open(ruta, 'r', encoding=enc, errors='replace', newline='') as f:
|
|
muestra = f.read(4096); f.seek(0)
|
|
try:
|
|
dialect = csv.Sniffer().sniff(muestra, delimiters=",;\t|")
|
|
except Exception:
|
|
dialect = csv.excel_tab if '\t' in muestra else csv.excel
|
|
return list(csv.reader(f, dialect))
|
|
except Exception:
|
|
pass
|
|
|
|
raise ultimo_error or UnicodeDecodeError("decode", b"", 0, 1, "No se pudo decodificar el CSV")
|
|
|
|
def nombre_salida(ruta_in, ruta_out=None):
|
|
if ruta_out: return ruta_out
|
|
base, _ = os.path.splitext(ruta_in)
|
|
return base + '_insert.txt'
|
|
|
|
def main():
|
|
if len(sys.argv) < 2:
|
|
print("Uso: python products_comands.py archivo.csv [salida.txt]", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
ruta_csv = sys.argv[1]
|
|
ruta_txt = nombre_salida(ruta_csv, sys.argv[2] if len(sys.argv) >= 3 else None)
|
|
|
|
filas = leer_csv(ruta_csv)
|
|
if filas and es_encabezado(filas[0]):
|
|
filas = filas[1:]
|
|
|
|
vistos = set() # para detectar id_producto repetidos
|
|
duplicadas = 0
|
|
valores = []
|
|
|
|
for fila in filas:
|
|
if not fila:
|
|
continue
|
|
idp = (fila[0] if len(fila) > 0 else '').strip()
|
|
nombre = fila[1] if len(fila) > 1 else ''
|
|
categoria = fila[2] if len(fila) > 2 else ''
|
|
|
|
if idp == '':
|
|
duplicadas += 1
|
|
continue
|
|
|
|
if idp in vistos:
|
|
duplicadas += 1
|
|
continue
|
|
vistos.add(idp)
|
|
|
|
valores.append(f"({esc(idp)}, {esc(nombre)}, {esc(categoria)})")
|
|
|
|
cols = ", ".join(COLUMNAS)
|
|
lineas = []
|
|
|
|
if INSERT_POR_FILA:
|
|
for v in valores:
|
|
lineas.append(f"INSERT INTO {TABLA} ({cols}) VALUES {v};")
|
|
else:
|
|
if BLOQUE and BLOQUE > 0:
|
|
for i in range(0, len(valores), BLOQUE):
|
|
chunk = valores[i:i+BLOQUE]
|
|
lineas.append(f"INSERT INTO {TABLA} ({cols}) VALUES")
|
|
lineas.append(",\n".join(chunk) + ";")
|
|
else:
|
|
lineas.append(f"INSERT INTO {TABLA} ({cols}) VALUES")
|
|
lineas.append(",\n".join(valores) + ";")
|
|
|
|
with open(ruta_txt, 'w', encoding='utf-8') as f:
|
|
f.write("\n".join(lineas))
|
|
|
|
print(f"Listo: {ruta_txt} (omitidas por duplicado/ vacío: {duplicadas})")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|