# profileAnalyzer/core/core.py # ... (tutti gli import e le altre classi/funzioni restano invariate) ... import pstats from io import StringIO import subprocess import sys import os from dataclasses import dataclass, field from typing import List, Optional from datetime import datetime @dataclass class LaunchProfile: name: str run_as_module: bool = False target_path: str = "" module_name: str = "" script_args: str = "" python_interpreter: str = sys.executable class ProfileAnalyzer: # ... (nessuna modifica qui) def __init__(self): self.stats: Optional[pstats.Stats] = None self.profile_path: Optional[str] = None def load_profile(self, filepath: str) -> bool: try: self.stats = pstats.Stats(filepath) self.stats.strip_dirs() self.profile_path = filepath return True except (FileNotFoundError, TypeError, OSError) as e: print(f"Error loading profile file '{filepath}': {e}") self.stats = None self.profile_path = None return False def get_stats(self, sort_by: str, limit: int = 200) -> list: if not self.stats: return [] s = StringIO() stats_to_print = pstats.Stats(self.profile_path, stream=s) stats_to_print.strip_dirs() stats_to_print.sort_stats(sort_by) stats_to_print.print_stats(limit) s.seek(0) lines = s.getvalue().splitlines() results = [] data_started = False for line in lines: if not line.strip(): continue if 'ncalls' in line and 'tottime' in line: data_started = True continue if data_started: parts = line.strip().split(maxsplit=5) if len(parts) == 6: try: results.append((parts[0], float(parts[1]), float(parts[2]), float(parts[3]), float(parts[4]), parts[5])) except (ValueError, IndexError): continue return results def run_and_profile_script(profile: LaunchProfile) -> Optional[str]: """Runs a target Python script/module under cProfile.""" # --- Output File Path Definition (prima di tutto) --- output_dir = os.path.join(os.getcwd(), "execution_profiles") os.makedirs(output_dir, exist_ok=True) timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") profile_name_sanitized = profile.name.replace(' ', '_').replace('.', '_') # **CORREZIONE**: Creare un percorso assoluto fin da subito profile_output_path = os.path.abspath(os.path.join(output_dir, f"{timestamp}_{profile_name_sanitized}.prof")) # --- Command and Working Directory Definition --- command = [profile.python_interpreter, "-m", "cProfile", "-o", profile_output_path] working_directory = None if profile.run_as_module: if not profile.module_name: print("Error: Module name is required.") return None # target_path in module mode is the project root if not profile.target_path or not os.path.isdir(profile.target_path): print(f"Error: Project Root Folder is not a valid directory: {profile.target_path}") return None # **CORREZIONE**: la sintassi corretta è '-m' seguito dal nome del modulo command.extend(["-m", profile.module_name]) working_directory = profile.target_path else: # **CORREZIONE**: target_path è il percorso dello script if not profile.target_path or not os.path.exists(profile.target_path): print(f"Error: Script path does not exist: {profile.target_path}") return None command.append(profile.target_path) working_directory = os.path.dirname(profile.target_path) if profile.script_args: command.extend(profile.script_args.split()) try: print(f"Executing profiling command: {' '.join(command)}") print(f"Working Directory for subprocess: {working_directory}") process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd=working_directory ) stdout, stderr = process.communicate() if stdout: print(f"--- STDOUT ---\n{stdout}") if stderr: print(f"--- STDERR ---\n{stderr}") if process.returncode != 0: print(f"Warning: Profiled script exited with non-zero status: {process.returncode}") if not os.path.exists(profile_output_path) or os.path.getsize(profile_output_path) == 0: print("Error: Profiling failed and no output file was generated.") return None print(f"Profiling data saved to: {profile_output_path}") return profile_output_path except Exception as e: print(f"Failed to run and profile script: {e}") return None