Pagina 1 di 1

xFinder - Ricerca file e cartelle [Python]

Inviato: 27/07/2024, 22:43
da FrancyDotNet
:info: Versione 1.0:Questo è il programma di base. Effettua la ricerca di files o cartella all'interno di una directory in modo ricorsivo e nei risultati ne restituisce i dettagli. Non sono state incluse alcune funzioni che ne avrebbero ottimizzato l'utilizzo proprio per fornire una miglior leggibilità del codice e rendere semplice il concetto di ricerca.

Codice: Seleziona tutto

import os

def search_files_and_folder(root_folder, search_name):
    results = []
    for root, dirs, files in os.walk(root_folder):
        if search_name in dirs + files:
            path = os.path.join(root, search_name)
            name, ext = os.path.splitext(search_name)
            dir_path = os.path.dirname(path)
            dir_path = dir_path.replace('/', '\\')
            size = os.path.getsize(path)
            size_kb = "{:,} KB".format(round(size/1024, 1))
            results.append((name, dir_path, ext, size_kb))
    return results

# Definisci la cartella di partenza per la ricerca
cartella_di_partenza = "F:/Dev/Progetti"

# Definisci il nome del file o della cartella da cercare
nome_file_o_cartella = "array.wad"

# Chiama la funzione search_files_and_folder per cercare il file o la cartella
results = search_files_and_folder(cartella_di_partenza, nome_file_o_cartella)

# Stampa i risultati della ricerca
if results:
    print(f"Trovati {len(results)} risultati per '{nome_file_o_cartella}':\n")
    for result in results:
        print(f"Nome: {result[0]}")
        print(f"Percorso: {result[1]}")
        print(f"Estensione: {result[2]}")
        print(f"Dimensioni: {result[3]}")
else:
    print(f"Nessun risultato trovato per '{nome_file_o_cartella}' nella cartella '{cartella_di_partenza}'.")
Considerazioni finali: Il codice è abbastanza efficiente, ma ci sono alcune possibili ottimizzazioni che si potrebbero considerare:
  • Utilizzare la libreria pathlib invece di os per le operazioni sui percorsi:
    La libreria pathlib offre una sintassi più pulita e orientata agli oggetti per le operazioni sui percorsi, ed è generalmente più facile da usare rispetto alla libreria os. Potresti provare a riscrivere la funzione search_files_and_folder utilizzando pathlib per migliorare la leggibilità e la manutenibilità del codice.
  • Utilizzare la funzione os.scandir invece di os.walk:
    La funzione os.scandir è più veloce di os.walk, poiché restituisce direttamente gli oggetti DirEntry relativi ai file e alle cartelle nella directory specificata. In questo modo, non è necessario eseguire la ricorsione sui sotto-directory e risparmi tempo.
  • Utilizzare il modulo multiprocessing per parallelizzare la ricerca:
    Se devi cercare in una grande quantità di file, potrebbe essere utile utilizzare il modulo multiprocessing per parallelizzare la ricerca su più processi. In questo modo, potresti sfruttare i multi-core del tuo processore e ridurre significativamente il tempo di esecuzione.
  • Utilizzare un generatore di espressioni per ridurre il consumo di memoria:
    Invece di creare una lista di risultati, potresti utilizzare le espressioni generator per ridurre il consumo di memoria. In questo modo, la funzione restituirà un generatore, che permette di ottenere i risultati man mano che vengono generati, anziché doverli memorizzare tutti in memoria.
  • Utilizzare pathlib per la formattazione dei percorsi:
    Quando devi convertire un percorso in un percorso Windows, anziché usare dir_path.replace('/', '\\'), potresti utilizzare il metodo as_posix() di pathlib.Path, che converte il percorso in un percorso POSIX e lo formatta automaticamente correttamente per la piattaforma corrente.
  • Utilizzarere la funzione fnmatch.fnmatch() per controllare se il nome del file o della cartella corrisponde al pattern specificato nella variabile search_name, che può contenere il carattere jolly * per rappresentare qualsiasi stringa di caratteri.

Re: xFinder - Ricerca file e cartelle [Python]

Inviato: 27/07/2024, 22:44
da FrancyDotNet
In questo post vorrei presentare le varianti del programma base, ovvero le versioni 1.5 - 2.0 - 3.0 che non sono altro che un'evoluzione rispetto alla precedente. Lo scopo sarebbe quello di mostrare le diverse opportunità che possono essere utilizzare quando si effettua una ricerca.



:info: Versione 1.5: Questa è una versione migliorata del programma di base inserendo le funzioni "seen" e "yield". È stato introdotto l'utilizzo della libreria "fnmatch" per un maggior controllo sul nome del percorso e per una gestione più flessibile dei caratteri jolly (come * oppure ?).
Inoltre è stata aggiunta una funzione per misurare il tempo impiegato durante la ricerca, una barra del progresso ed infine sono state aggiunte le informazioni sulle date e sui permessi.

Codice: Seleziona tutto

import os
import time
import fnmatch
from datetime import datetime

def search_files_and_folder(root_folder, search_filename):
    # Qui vengono contati quanti files e cartelle dovranno essere elaborati
    mid_time = time.time()
    total_files = 0
    for root, dirs, files in os.walk(root_folder):
        total_files += len(dirs + files)
    current_file = 0
    print (f"Conteggio totale files e cartelle: {total_files} ; Eseguito in: {time.time() - mid_time:.2f} secondi")
    # Qui parte la funzione di ricerca
    seen = set()  # set di path già visitati
    for root, dirs, files in os.walk(root_folder):
        for filename in (dirs + files):
            current_file += 1
            progress_bar(current_file, total_files)
            if fnmatch.fnmatch(filename, search_filename) and filename not in seen:
                path = os.path.join(root, filename)
                name = os.path.basename(path)
                ext = os.path.splitext(path)[1]
                dir_path = os.path.dirname(path)
                dir_path = os.path.normpath(os.path.join(dir_path))
                size = os.path.getsize(path)
                size_kb = "{:,} KB".format(round(size/1024, 1))
                last_modified = datetime.fromtimestamp(os.path.getmtime(path)).strftime('%d/%m/%Y')
                creation_time = datetime.fromtimestamp(os.path.getctime(path)).strftime('%d/%m/%Y')
                permissions = oct(os.stat(path).st_mode)[-3:]
                seen.add(filename)
                yield (name, dir_path, ext, size_kb, last_modified, creation_time, permissions)
    print("\n")
    return results

# Imposta la barra del progresso
def progress_bar(current, total):
    toolbar_width = 40
    percent = float(current) * 100 / total
    bar_width = int(percent / 100 * toolbar_width)
    print(f"Progresso: [{'#' * bar_width}{' ' * (toolbar_width - bar_width)}] {percent:.1f}% ", end="\r")

# Definisci la cartella di partenza per la ricerca
cartella_di_partenza = "C:/tmp"

# Definisci il nome del file o della cartella da cercare
nome_file_o_cartella = "array*"

# Misura il tempo di esecuzione della ricerca
start_time = time.time()

# Chiama la funzione search_files_and_folder per cercare il file o la cartella
results = search_files_and_folder(cartella_di_partenza, nome_file_o_cartella)

# Stampa i risultati della ricerca
if results:
    print(f"Trovati i seguenti risultati per '{nome_file_o_cartella}':\n")
    for result in results:
        print("\n")
        print(f"Nome: {result[0]}")
        print(f"Percorso: {result[1]}")
        print(f"Estensione: {result[2]}")
        print(f"Dimensioni: {result[3]}")
        print(f"Ultima modifica: {result[4]}")
        print(f"Data di creazione: {result[5]}")
        print(f"Permessi: {result[6]}\n")
else:
    print(f"Nessun risultato trovato per '{nome_file_o_cartella}' nella cartella '{cartella_di_partenza}'.")

# Stampa il tempo di esecuzione della ricerca
print(f"Tempo di esecuzione complessivo: {time.time() - start_time:.2f} secondi")



:info: Versione 2.0: Il programma base è stato modificato per utilizzare un sistema di caching. Inoltre è stata aggiunta una funzione per misurare il tempo impiegato durante la ricerca ed infine sono state aggiunte le informazioni sulle date e sui permessi.

Codice: Seleziona tutto

import os
import time
from datetime import datetime

class SmartCache:
    def __init__(self):
        self.cache = {}

    def search(self, root_folder, search_filename):
        if search_filename in self.cache:
            # Ritorna i risultati della cache
            return self.cache[search_filename]

        # Cerca i file e le cartelle
        results = []
        for root, dirs, files in os.walk(root_folder):
            if search_filename in dirs + files:
                path = os.path.join(root, search_filename)
                name, ext = os.path.splitext(search_filename)
                dir_path = os.path.dirname(path)
                dir_path = dir_path.replace('/', '\\')
                size = os.path.getsize(path)
                size_kb = "{:,} KB".format(round(size/1024, 1))
                last_modified = datetime.fromtimestamp(os.path.getmtime(path)).strftime('%d/%m/%Y')
                creation_time = datetime.fromtimestamp(os.path.getctime(path)).strftime('%d/%m/%Y')
                permissions = oct(os.stat(path).st_mode)[-3:]
                results.append((name, dir_path, ext, size_kb, last_modified, creation_time, permissions))

        # Salva i risultati nella cache
        self.cache[search_filename] = results

        return results

# Definisci la cartella di partenza per la ricerca
cartella_di_partenza = "C:/tmp"

# Definisci il nome del file o della cartella da cercare
nome_file_o_cartella = "array.wad"

# Misura il tempo di esecuzione della ricerca
start_time = time.time()

# Crea un oggetto SmartCache
cache = SmartCache()

# Chiama il metodo search della cache per cercare il file o la cartella
results = cache.search(cartella_di_partenza, nome_file_o_cartella)

# Stampa i risultati della ricerca
if results:
    print(f"Trovati {len(results)} risultati per '{nome_file_o_cartella}':\n")
    for result in results:
        print(f"Nome: {result[0]}")
        print(f"Percorso: {result[1]}")
        print(f"Estensione: {result[2]}")
        print(f"Dimensioni: {result[3]}")
        print(f"Ultima modifica: {result[4]}")
        print(f"Data di creazione: {result[5]}")
        print(f"Permessi: {result[6]}\n")
else:
    print(f"Nessun risultato trovato per '{nome_file_o_cartella}' nella cartella '{cartella_di_partenza}'.")

# Stampa il tempo di esecuzione della ricerca
print(f"Tempo di esecuzione: {time.time() - start_time:.2f} secondi")



:info: Versione 3.0: Questa è una versione migliorata del programma di base inserendo le funzioni "seen" e "yield". Inoltre è stata aggiunta una funzione per misurare il tempo impiegato durante la ricerca ed infine sono state aggiunte le informazioni sulle date e sui permessi.

Codice: Seleziona tutto

import os
import time
from datetime import datetime

def search_files_and_folder(root_folder, search_filename):
    seen = set()  # set di path già visitati
    for root, dirs, files in os.walk(root_folder):
        for filename in files:
            if search_filename == filename and filename not in seen:
                path = os.path.join(root, filename)
                name, ext = os.path.splitext(filename)
                dir_path = os.path.dirname(path)
                dir_path = dir_path.replace('/', '\\')
                size = os.path.getsize(path)
                size_kb = "{:,} KB".format(round(size/1024, 1))
                last_modified = datetime.fromtimestamp(os.path.getmtime(path)).strftime('%d/%m/%Y')
                creation_time = datetime.fromtimestamp(os.path.getctime(path)).strftime('%d/%m/%Y')
                permissions = oct(os.stat(path).st_mode)[-3:]
                seen.add(filename)
                yield (name, dir_path, ext, size_kb, last_modified, creation_time, permissions)

# Definisci la cartella di partenza per la ricerca
cartella_di_partenza = "C:/tmp"

# Definisci il nome del file o della cartella da cercare
nome_file_o_cartella = "array.wad"

# Misura il tempo di esecuzione della ricerca
start_time = time.time()

# Chiama la funzione search_files_and_folder per cercare il file o la cartella
results = search_files_and_folder(cartella_di_partenza, nome_file_o_cartella)

# Stampa i risultati della ricerca
if results:
    print(f"Trovati i seguenti risultati per '{nome_file_o_cartella}':\n")
    for result in results:
        print(f"Nome: {result[0]}")
        print(f"Percorso: {result[1]}")
        print(f"Estensione: {result[2]}")
        print(f"Dimensioni: {result[3]}")
        print(f"Ultima modifica: {result[4]}")
        print(f"Data di creazione: {result[5]}")
        print(f"Permessi: {result[6]}\n")
else:
    print(f"Nessun risultato trovato per '{nome_file_o_cartella}' nella cartella '{cartella_di_partenza}'.")

# Stampa il tempo di esecuzione della ricerca
print(f"Tempo di esecuzione complessivo: {time.time() - start_time:.2f} secondi")

Re: xFinder - Ricerca file e cartelle [Python]

Inviato: 27/07/2024, 22:44
da FrancyDotNet
:coool: Versione finale con interfaccia grafica!!! Scrivere il progetto aggiornato + link a GitHub!

Codice: Seleziona tutto

from pathlib import Path
from datetime import datetime
import math
import fnmatch
import threading
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from tkcalendar import DateEntry

# Flag per l'interruzione della ricerca
interrupt_flag = False

# Gruppo widget per il filtro data (popolato dopo la creazione dei widget)
widget_filtri_data = []

def inizializza_avvio():
    percorso_corrente = str(Path.cwd())
    cmbPercorso.set(percorso_corrente)

    unit_list = leggi_unita_attive()
    valori = list(cmbPercorso["values"])
    for unit in unit_list:
        if unit not in valori:
            valori.append(unit)
    if percorso_corrente not in valori:
        valori.append(percorso_corrente)
    cmbPercorso["values"] = valori

    btnStop.config(state=tk.DISABLED)
    cmbNome.focus_set()

def leggi_unita_attive():
    return [f"{chr(d)}:\\" for d in range(ord('A'), ord('Z') + 1) if Path(f"{chr(d)}:\\").exists()]

def cerca_files_cartelle(cartella_radice, nome_da_cercare, callback_stato=None):
    global interrupt_flag
    risultati = []
    nome_lower = nome_da_cercare.lower()
    usa_wildcard = "*" in nome_da_cercare

    dt_inizio, dt_fine = None, None
    if varDataAttiva.get() == 1:
        try:
            dt_inizio = datetime.strptime(f"{calDataInizio.get()} {spnOraInizio.get()}:{spnMinInizio.get()}", "%d/%m/%Y %H:%M")
            dt_fine = datetime.strptime(f"{calDataFine.get()} {spnOraFine.get()}:{spnMinFine.get()}", "%d/%m/%Y %H:%M")
        except Exception as e:
            messagebox.showerror("Errore data", f"Formato data/ora non valido: {e}")
            return []

    percorso = Path(cartella_radice)
    try:
        files = percorso.rglob("*") if varSubDir.get() else percorso.glob("*")
    except Exception as e:
        messagebox.showerror("Errore accesso", f"Impossibile accedere a: {cartella_radice}\n\n{e}")
        return []

    for elemento in files:
        if interrupt_flag:
            interrupt_flag = False
            return risultati

        if callback_stato:
            callback_stato(str(elemento.parent))

        nome = elemento.name
        if (usa_wildcard and fnmatch.fnmatch(nome, nome_da_cercare)) or (not usa_wildcard and nome_lower in nome.lower()):
            try:
                info = elemento.stat()
                mtime = datetime.fromtimestamp(info.st_mtime)
                if dt_inizio and dt_fine and not (dt_inizio <= mtime <= dt_fine):
                    continue

                risultati.append((
                    nome,
                    str(elemento.parent),
                    dimensione_elemento(info.st_size),
                    elemento.suffix,
                    datetime.fromtimestamp(info.st_ctime).strftime('%d %B %Y'),
                    mtime.strftime('%d %B %Y')
                ))
            except:
                continue

    return risultati

def interrompi_ricerca():
    global interrupt_flag
    interrupt_flag = True
    lblBarraStato.config(text="Ricerca interrotta.")

def dimensione_elemento(size_bytes):
    if size_bytes == 0:
        return "0 B"
    try:
        i = int(math.log(size_bytes, 1024))
        p = 1024 ** i
        return f"{size_bytes / p:.0f} {'B KMGT'[i]}B"
    except:
        return "???"

def btnTrova_Click():
    cartella = cmbPercorso.get()
    nome = cmbNome.get()

    tvRisultati.delete(*tvRisultati.get_children())

    if not cartella or not nome:
        messagebox.showwarning("Attenzione", "Inserisci sia il percorso della cartella che il nome del file/cartella da cercare.")
        return

    btnStop.config(state=tk.NORMAL)
    lblBarraStato.config(text=f"Ricerca in corso in: {cartella}")

    threading.Thread(
        target=esegui_ricerca_thread,
        args=(cartella, nome),
        daemon=True
    ).start()

def esegui_ricerca_thread(cartella, nome):
    risultati = cerca_files_cartelle(cartella, nome, callback_stato=lambda p: frmMain.after(0, aggiorna_barra_stato, p))
    frmMain.after(0, aggiorna_risultati_gui, risultati)

def aggiorna_risultati_gui(risultati):
    for riga in risultati:
        tvRisultati.insert("", 1, text=str(riga[0]), values=(riga[1], riga[2], riga[3], riga[4], riga[5]))

    btnStop.config(state=tk.DISABLED)
    lblBarraStato.config(text=f"Ricerca completata. {len(risultati)} risultati trovati.")

def aggiorna_barra_stato(percorso_corrente):
    lblBarraStato.config(text=f"Cercando in: {percorso_corrente}")

def btnSfoglia_Click():
    percorso_ricerca = filedialog.askdirectory(parent=frmMain, initialdir=str(Path.cwd()), title="Selezionare la cartella di ricerca:")
    if percorso_ricerca:
        path_sel = Path(percorso_ricerca).resolve()
        valori = list(cmbPercorso["values"])
        if str(path_sel) not in valori:
            valori.append(str(path_sel))
            cmbPercorso["values"] = valori
        cmbPercorso.set(str(path_sel))

def btnNuovaRicerca_Click():
    cmbNome.set("")
    tvRisultati.delete(*tvRisultati.get_children())
    cmbNome.focus_set()

def chkDataAttiva_Check():
    stato = 'normal' if varDataAttiva.get() == 1 else 'disabled'
    for w in widget_filtri_data:
        w.config(state=stato)

#---  Finestra principale ---
frmMain = tk.Tk()
frmMain.title("PowerApps - xFinder")
frmMain.geometry("800x500")
frmMain.resizable(False, False)
frmMain.iconbitmap('images/Search95.ico')

# Icona pixel art XF
#icon = PhotoImage(width=16, height=16)
#icon.put("#0000cc", to=(0, 0, 16, 16))
#x_pixels = [(1, 1), (2, 2), (3, 3), (4, 4), (1, 4), (2, 3), (3, 2), (4, 1)]
#f_pixels = [(7, 6), (8, 6), (9, 6), (7, 7), (7, 8), (7, 9),
#            (8, 8), (9, 8), (7, 10), (7, 11)]
#for x, y in x_pixels + f_pixels:
#    icon.put("#ffffff", (x, y))
#frmMain.iconphoto(False, icon)

# Pulsanti principali
btnTrova = ttk.Button(frmMain, text="Trova", command=btnTrova_Click)
btnTrova.place(x=700, y=26, height=25, width=90)

btnStop = ttk.Button(frmMain, text="Interrompi", command=interrompi_ricerca)
btnStop.place(x=700, y=56, height=25, width=90)

btnNuovaRicerca = ttk.Button(frmMain, text="Nuova ricerca", command=btnNuovaRicerca_Click)
btnNuovaRicerca.place(x=700, y=86, height=25, width=90)

#--- Creazione Notebook (frame) con 3 schede ---
notebook = ttk.Notebook(frmMain)
pgPercorso = ttk.Frame(notebook)
pgData = ttk.Frame(notebook)
pgAvanzate = ttk.Frame(notebook)

notebook.add(pgPercorso, text="Nome e percorso")
notebook.add(pgData, text="Data")
notebook.add(pgAvanzate, text="Avanzate")
notebook.select(pgPercorso)
notebook.place(x=4, y=4, height=184, width=690)

#--- Contenuto Frame #1 ---
lblNome = ttk.Label(pgPercorso, anchor='e', text="Nome:")
lblNome.place(x=10, y=20, height=25, width=54)

cmbNome = ttk.Combobox(pgPercorso)
cmbNome.bind("<Return>", lambda event: btnTrova_Click())
cmbNome.place(x=70, y=20, height=25, width=600)

lblPercorso = ttk.Label(pgPercorso, anchor='e', text="Cerca in:")
lblPercorso.place(x=10, y=60, height=25, width=54)

cmbPercorso = ttk.Combobox(pgPercorso, state='readonly')
cmbPercorso.place(x=70, y=60, height=25, width=500)

btnSfoglia = ttk.Button(pgPercorso, text="Sfoglia", command=btnSfoglia_Click)
btnSfoglia.place(x=580, y=60, height=25, width=90)

varSubDir = tk.IntVar(value=1)
chkSubDir = ttk.Checkbutton(pgPercorso, text="Ricerca nelle sottocartelle", onvalue=1, offvalue=0, variable=varSubDir)
chkSubDir.place(x=70, y=100, height=25, width=160)

##---Contenuto Frame #2---
varDataAttiva = tk.IntVar(value=0)
chkDataAttiva = ttk.Checkbutton(pgData, text="Abilita filtro per data ultima modifica:", variable=varDataAttiva, onvalue=1, offvalue=0, command=chkDataAttiva_Check)
chkDataAttiva.place(x=10, y=10, height=25)

lblDataInizio = ttk.Label(pgData, text="Data da:", anchor='e')
lblDataInizio.place(x=10, y=40, width=54, height=25)

calDataInizio = DateEntry(pgData, width=12, background='darkblue', foreground='white', borderwidth=2, date_pattern='dd/mm/yyyy')
calDataInizio.set_date(datetime.now())
calDataInizio.place(x=70, y=40, height=25)

lblOraInizio = ttk.Label(pgData, text="ora:")
lblOraInizio.place(x=170, y=40, height=25)

spnOraInizio = tk.Spinbox(pgData, from_=0, to=23, width=2, format="%02.0f")
spnOraInizio.place(x=200, y=40, height=25, width=40)

lblSep1 = ttk.Label(pgData, text=":")
lblSep1.place(x=240, y=40, width=10, height=25)

spnMinInizio = tk.Spinbox(pgData, from_=0, to=59, width=2, format="%02.0f")
spnMinInizio.place(x=250, y=40, height=25, width=40)

lblDataFine = ttk.Label(pgData, text="a:", anchor='e')
lblDataFine.place(x=10, y=80, width=54, height=25)

calDataFine = DateEntry(pgData, width=12, background='darkblue', foreground='white', borderwidth=2, date_pattern='dd/mm/yyyy')
calDataFine.set_date(datetime.now())
calDataFine.place(x=70, y=80, height=25)

lblOraFine = ttk.Label(pgData, text="ora:")
lblOraFine.place(x=170, y=80, height=25)

spnOraFine = tk.Spinbox(pgData, from_=0, to=23, width=2, format="%02.0f")
spnOraFine.place(x=200, y=80, height=25, width=40)

lblSep2 = ttk.Label(pgData, text=":")
lblSep2.place(x=240, y=80, width=10, height=25)

spnMinFine = tk.Spinbox(pgData, from_=0, to=59, width=2, format="%02.0f")
spnMinFine.place(x=250, y=80, height=25, width=40)
chkDataAttiva_Check()

##---Contenuto Frame #3---

#--- Contenuto Finestra principale ---
tvRisultati = ttk.Treeview(frmMain)
tvRisultati["columns"] = ("#0", "#1", "#2", "#3", "#4", "#5")
tvRisultati.column("#0", width=200, minwidth=200)
tvRisultati.column("#1", width=220, minwidth=220)
tvRisultati.column("#2", width=80, minwidth=80)
tvRisultati.column("#3", width=50, minwidth=50)
tvRisultati.column("#4", width=100, minwidth=100)
tvRisultati.column("#5", width=100, minwidth=100)
tvRisultati.heading("#0", text="Nome")
tvRisultati.heading("#1", text="Nella cartella")
tvRisultati.heading("#2", text="Dimensione")
tvRisultati.heading("#3", text="Tipo")
tvRisultati.heading("#4", text="Data creazione")
tvRisultati.heading("#5", text="Data modifica")
tvRisultati.place(x=4, y=200, height=266, width=770)

sbVerticale = ttk.Scrollbar(frmMain, orient="vertical", command=tvRisultati.yview)
sbVerticale.place(x=775, y=200, height=266)
tvRisultati.configure(yscrollcommand=sbVerticale.set)

lblBarraStato = ttk.Label(frmMain, text="Pronto.", relief=tk.SUNKEN, anchor='w')
lblBarraStato.place(x=4, y=468, width=790, height=24)

if __name__ == "__main__":
    inizializza_avvio()

frmMain.mainloop()