import argparse import subprocess import os import sys import locale import glob # <--- Importar glob para buscar archivos # (Función get_console_encoding y variable CONSOLE_ENCODING como en la respuesta anterior) def get_console_encoding(): """Obtiene la codificación preferida de la consola, con fallback.""" try: return locale.getpreferredencoding(False) except Exception: return "cp1252" CONSOLE_ENCODING = get_console_encoding() # Descomenta la siguiente línea si quieres ver la codificación detectada: # print(f"Detected console encoding: {CONSOLE_ENCODING}") # (Función run_script como en la respuesta anterior, usando CONSOLE_ENCODING) def run_script(script_name, xml_arg): """Runs a given script with the specified XML file argument.""" script_path = os.path.join(os.path.dirname(__file__), script_name) command = [sys.executable, script_path, xml_arg] print(f"\n--- Running {script_name} with argument: {xml_arg} ---") try: result = subprocess.run( command, check=True, capture_output=True, text=True, encoding=CONSOLE_ENCODING, errors="replace", ) # 'replace' para evitar errores # Imprimir stdout y stderr # Eliminar saltos de línea extra al final si existen stdout_clean = result.stdout.strip() stderr_clean = result.stderr.strip() if stdout_clean: print(stdout_clean) if stderr_clean: print("--- Stderr ---") print(stderr_clean) print("--------------") print(f"--- {script_name} finished successfully ---") return True except FileNotFoundError: print(f"Error: Script '{script_path}' not found.") return False except subprocess.CalledProcessError as e: print(f"Error running {script_name}:") print(f"Return code: {e.returncode}") stdout_decoded = ( e.stdout.decode(CONSOLE_ENCODING, errors="replace").strip() if isinstance(e.stdout, bytes) else (e.stdout or "").strip() ) stderr_decoded = ( e.stderr.decode(CONSOLE_ENCODING, errors="replace").strip() if isinstance(e.stderr, bytes) else (e.stderr or "").strip() ) if stdout_decoded: print("--- Stdout ---") print(stdout_decoded) if stderr_decoded: print("--- Stderr ---") print(stderr_decoded) print("--------------") return False except Exception as e: print(f"An unexpected error occurred while running {script_name}: {e}") return False # --- NUEVA FUNCIÓN PARA SELECCIONAR ARCHIVO --- def select_xml_file(): """Busca archivos .xml, los lista y pide al usuario que elija uno.""" print("No XML file specified. Searching for XML files in current directory...") # Buscar archivos .xml en el directorio actual (.) xml_files = sorted(glob.glob("*.xml")) # sorted para orden alfabético if not xml_files: print("Error: No .xml files found in the current directory.") sys.exit(1) print("\nAvailable XML files:") for i, filename in enumerate(xml_files, start=1): print(f" {i}: {filename}") while True: try: choice = input( f"Enter the number of the file to process (1-{len(xml_files)}): " ) choice_num = int(choice) if 1 <= choice_num <= len(xml_files): selected_file = xml_files[choice_num - 1] print(f"Selected: {selected_file}") return selected_file else: print("Invalid choice. Please enter a number from the list.") except ValueError: print("Invalid input. Please enter a number.") except EOFError: # Manejar si la entrada se cierra inesperadamente print("\nSelection cancelled.") sys.exit(1) # --- FIN NUEVA FUNCIÓN --- if __name__ == "__main__": # Imports necesarios para esta sección import os import sys import glob # Asegúrate de que glob esté importado al principio del archivo # Directorio base donde buscar los archivos XML (relativo al script) base_search_dir = "XML Project" script_dir = os.path.dirname(__file__) # Directorio donde está x0_main.py 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." ) print( "Por favor, crea el directorio 'XML Project' en la misma carpeta que este script y coloca tus archivos XML dentro." ) sys.exit(1) # Buscar todos los archivos .xml recursivamente dentro de xml_project_dir # Usamos os.path.join para construir la ruta de búsqueda correctamente # y '**/*.xml' para la recursividad con glob 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:") # Ordenar para un procesamiento predecible (opcional) xml_files_found.sort() for xml_file in xml_files_found: # Imprimir la ruta relativa desde el directorio del script para claridad print(f" - {os.path.relpath(xml_file, script_dir)}") # Scripts a ejecutar en secuencia (asegúrate que los nombres son correctos) script1 = "x1_to_json.py" script2 = "x2_process.py" script3 = "x3_generate_scl.py" # Procesar cada archivo encontrado processed_count = 0 failed_count = 0 for xml_filepath in xml_files_found: print( f"\n--- Iniciando pipeline para: {os.path.relpath(xml_filepath, script_dir)} ---" ) # Usar la ruta absoluta para evitar problemas si los scripts cambian de directorio absolute_xml_filepath = os.path.abspath(xml_filepath) # Ejecutar los scripts en secuencia para el archivo actual # La función run_script ya está definida en tu script x0_main.py success = True if not run_script(script1, absolute_xml_filepath): print( f"\nPipeline falló en el script '{script1}' para el archivo: {os.path.relpath(xml_filepath, script_dir)}" ) success = False elif not run_script(script2, absolute_xml_filepath): print( f"\nPipeline falló en el script '{script2}' para el archivo: {os.path.relpath(xml_filepath, script_dir)}" ) success = False elif not run_script(script3, absolute_xml_filepath): print( f"\nPipeline falló en el script '{script3}' para el archivo: {os.path.relpath(xml_filepath, script_dir)}" ) success = False if success: print( f"--- Pipeline completado exitosamente para: {os.path.relpath(xml_filepath, script_dir)} ---" ) processed_count += 1 else: failed_count += 1 print( f"--- Pipeline falló para: {os.path.relpath(xml_filepath, script_dir)} ---" ) 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("---------------------------------------") xml_filename = None # Comprobar si se pasó un argumento de línea de comandos # sys.argv[0] es el nombre del script, sys.argv[1] sería el primer argumento if len(sys.argv) > 1: # Si hay argumentos, usar argparse para parsearlo (permite -h, etc.) parser = argparse.ArgumentParser( description="Run the Simatic XML processing pipeline." ) parser.add_argument( "xml_file", # Ya no necesitamos nargs='?' ni default aquí porque sabemos que hay un argumento help="Path to the XML file to process.", ) # Parsear solo los argumentos conocidos, ignorar extras si los hubiera args, unknown = parser.parse_known_args() xml_filename = args.xml_file print(f"XML file specified via argument: {xml_filename}") else: # Si no hay argumentos, llamar a la función interactiva xml_filename = select_xml_file() # --- El resto del script continúa igual, usando xml_filename --- # Verificar si el archivo XML de entrada (seleccionado o pasado) existe if not os.path.exists(xml_filename): print(f"Error: Selected or specified XML file not found: {xml_filename}") sys.exit(1) print(f"\nStarting pipeline for: {xml_filename}") # Run scripts sequentially (asegúrate que los nombres son correctos) script1 = "x1_to_json.py" script2 = "x2_process.py" script3 = "x3_generate_scl.py" if run_script(script1, xml_filename): if run_script(script2, xml_filename): if run_script(script3, xml_filename): print("\nPipeline completed successfully.") else: print("\nPipeline failed at script:", script3) else: print("\nPipeline failed at script:", script2) else: print("\nPipeline failed at script:", script1)