Simatic_XML_Parser_to_SCL/x0_main.py

214 lines
8.1 KiB
Python

import argparse
import subprocess
import os
import sys
import locale
import glob
# (Función get_console_encoding y variable CONSOLE_ENCODING como antes)
def get_console_encoding():
"""Obtiene la codificación preferida de la consola, con fallback."""
try:
return locale.getpreferredencoding(False)
except Exception:
# Fallback común en Windows si falla getpreferredencoding
return "cp1252" # O prueba con 'utf-8' si cp1252 da problemas
CONSOLE_ENCODING = get_console_encoding()
# print(f"Detected console encoding: {CONSOLE_ENCODING}")
# (Función run_script como antes, usando CONSOLE_ENCODING)
def run_script(script_name, xml_arg):
"""Runs a given script with the specified XML file argument."""
# Asegurarse que la ruta al script sea absoluta o relativa al script actual
script_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), script_name)
# Usar la ruta absoluta al ejecutable de Python actual
python_executable = sys.executable
command = [
python_executable,
script_path,
xml_arg,
] # Usar la ruta absoluta de python
print(f"\n--- Running {script_name} with argument: {xml_arg} ---")
try:
# Ejecutar el proceso hijo
result = subprocess.run(
command,
check=True, # Lanza excepción si el script falla (return code != 0)
capture_output=True, # Captura stdout y stderr
text=True, # Decodifica stdout/stderr como texto
encoding=CONSOLE_ENCODING, # Usa la codificación detectada
errors="replace", # Reemplaza caracteres no decodificables
)
# Imprimir stdout y stderr si no están vacíos
stdout_clean = result.stdout.strip() if result.stdout else ""
stderr_clean = result.stderr.strip() if result.stderr else ""
if stdout_clean:
print(stdout_clean)
if stderr_clean:
# Imprimir stderr claramente para errores del script hijo
print(
f"--- Stderr ({script_name}) ---", file=sys.stderr
) # Imprimir en stderr
print(stderr_clean, file=sys.stderr)
print("--------------------------", file=sys.stderr)
print(f"--- {script_name} finished successfully ---")
return True # Indicar éxito
except FileNotFoundError:
# Error si el script python o el ejecutable no se encuentran
print(
f"Error: Script '{script_path}' or Python executable '{python_executable}' not found.",
file=sys.stderr,
)
return False
except subprocess.CalledProcessError as e:
# Error si el script hijo devuelve un código de error (ej., sys.exit(1))
print(
f"Error running {script_name}: Script returned non-zero exit code {e.returncode}.",
file=sys.stderr,
)
# Decodificar e imprimir stdout/stderr del proceso fallido
stdout_decoded = e.stdout.strip() if e.stdout else ""
stderr_decoded = e.stderr.strip() if e.stderr else ""
if stdout_decoded:
print(f"--- Stdout ({script_name}) ---", file=sys.stderr)
print(stdout_decoded, file=sys.stderr)
if stderr_decoded:
print(f"--- Stderr ({script_name}) ---", file=sys.stderr)
print(stderr_decoded, file=sys.stderr)
print("--------------------------", file=sys.stderr)
return False # Indicar fallo
except Exception as e:
# Otros errores inesperados
print(
f"An unexpected error occurred while running {script_name}: {e}",
file=sys.stderr,
)
# Imprimir traceback para depuración
import traceback
traceback.print_exc(file=sys.stderr)
return False # Indicar fallo
# --- NO SE NECESITA select_xml_file() si procesamos todos ---
if __name__ == "__main__":
# --- PARTE 1: BUSCAR ARCHIVOS ---
# Directorio base donde buscar los archivos XML (relativo al script)
base_search_dir = "XML Project"
# Obtener la ruta absoluta del directorio donde está x0_main.py
script_dir = os.path.dirname(os.path.abspath(__file__))
xml_project_dir = os.path.join(script_dir, base_search_dir)
print(f"Buscando archivos XML recursivamente en: '{xml_project_dir}'")
# Verificar si el directorio 'XML Project' existe
if not os.path.isdir(xml_project_dir):
print(
f"Error: El directorio '{xml_project_dir}' no existe o no es un directorio.",
file=sys.stderr,
)
print(
"Por favor, crea el directorio 'XML Project' en la misma carpeta que este script y coloca tus archivos XML dentro."
)
sys.exit(1) # Salir con error
# Buscar todos los archivos .xml recursivamente
search_pattern = os.path.join(xml_project_dir, "**", "*.xml")
xml_files_found = glob.glob(search_pattern, recursive=True)
if not xml_files_found:
print(
f"No se encontraron archivos XML en '{xml_project_dir}' o sus subdirectorios."
)
sys.exit(0) # Salir limpiamente si no hay archivos
print(f"Se encontraron {len(xml_files_found)} archivos XML para procesar:")
xml_files_found.sort() # Ordenar para consistencia
for xml_file in xml_files_found:
print(f" - {os.path.relpath(xml_file, script_dir)}")
# --- PARTE 2: PROCESAR CADA ARCHIVO ---
# Scripts a ejecutar en secuencia
script1 = "x1_to_json.py"
script2 = "x2_process.py"
script3 = "x3_generate_scl.py"
processed_count = 0
failed_count = 0
# Procesar cada archivo encontrado en el bucle
for xml_filepath in xml_files_found:
relative_path = os.path.relpath(xml_filepath, script_dir)
print(f"\n--- Iniciando pipeline para: {relative_path} ---")
# Usar la ruta absoluta para los scripts hijos
absolute_xml_filepath = os.path.abspath(xml_filepath)
# Derivar nombres esperados para archivos intermedios (para depuración)
xml_base_name = os.path.splitext(os.path.basename(absolute_xml_filepath))[0]
xml_dir = os.path.dirname(absolute_xml_filepath)
parsing_dir = os.path.join(xml_dir, "parsing")
expected_json_file = os.path.join(parsing_dir, f"{xml_base_name}.json")
expected_processed_json = os.path.join(
parsing_dir, f"{xml_base_name}_processed.json"
)
# Ejecutar los scripts en secuencia
success = True
if not run_script(script1, absolute_xml_filepath):
print(
f"\nPipeline falló en el script '{script1}' para el archivo: {relative_path}",
file=sys.stderr,
)
success = False
elif not run_script(script2, absolute_xml_filepath):
print(
f"\nPipeline falló en el script '{script2}' para el archivo: {relative_path}",
file=sys.stderr,
)
success = False
elif not run_script(script3, absolute_xml_filepath):
print(
f"\nPipeline falló en el script '{script3}' para el archivo: {relative_path}",
file=sys.stderr,
)
success = False
# Actualizar contadores y mostrar estado
if success:
print(f"--- Pipeline completado exitosamente para: {relative_path} ---")
processed_count += 1
else:
failed_count += 1
print(
f"--- Pipeline falló para: {relative_path} ---", file=sys.stderr
) # Indicar fallo
# --- PARTE 3: RESUMEN FINAL ---
print("\n--- Resumen Final del Procesamiento ---")
print(f"Total de archivos XML encontrados: {len(xml_files_found)}")
print(
f"Archivos procesados exitosamente por el pipeline completo: {processed_count}"
)
print(f"Archivos que fallaron en algún punto del pipeline: {failed_count}")
print("---------------------------------------")
# Salir con código 0 si todo fue bien, 1 si hubo fallos
if failed_count > 0:
sys.exit(1)
else:
sys.exit(0)
# --- FIN: Se elimina la lógica redundante que venía después del bucle ---