Why my python file can only execute via console?

My code is this:

import os
import tkinter as tk
from tkinter import filedialog
import subprocess

def listar_roms_en_directorio(ruta_directorio):
    try:
        archivos = os.listdir(ruta_directorio)
        roms = [archivo for archivo in archivos if archivo.lower().endswith((".nes", ".snes", ".smc"))]
        return roms
    except FileNotFoundError:
        print(f"Directorio '{ruta_directorio}' no encontrado.")
        return []

def seleccionar_rom(roms):
    if not roms:
        print("No se encontraron ROMs en el directorio.")
        return None

    try:
        opcion = int(input("Selecciona un número de ROM: "))
        if 1 <= opcion <= len(roms):
            return roms[opcion - 1]
        else:
            print("Opción inválida. Introduce un número válido.")
            return None
    except ValueError:
        print("Introduce un número válido.")
        return None

def ejecutar_rom_con_zsnes(ruta_zsnes, ruta_rom):
    try:
        # Comando para ejecutar ZSNES con la ROM
        comando = [ruta_zsnes, ruta_rom]
        
        # Ejecutar el comando
        subprocess.run(comando)
        print(f"Se ejecutó la ROM '{ruta_rom}' con ZSNES.")
    except FileNotFoundError:
        print(f"ZSNES no encontrado en la ruta '{ruta_zsnes}'.")

# Directorio donde se encuentran las ROMs
directorio_roms = "roms"  # Reemplaza con la ruta real de tu directorio de ROMs
roms_en_directorio = listar_roms_en_directorio(directorio_roms)

while True:
    if roms_en_directorio:
        rom_seleccionada = seleccionar_rom(roms_en_directorio)
        if rom_seleccionada:
            ruta_zsnes = "zsnesw.exe"  # Reemplaza con la ruta real de ZSNES
            ejecutar_rom_con_zsnes(ruta_zsnes, os.path.join(directorio_roms, rom_seleccionada))
    else:
        print("No se encontraron ROMs en el directorio especificado.")

This appears working correctly with this using the ‘python3 reader.py’ in windows console…
But… when i click it, or compile to exe with auto-py-to-exe it shows me a repeated command and doesnst work correctly to choose rom.

These imports are not used. Is some other code elsewhere required?

More importantly, if your script is run from a directory, from which "roms" is empty or not valid, or causes the first call to listar_roms_en_directorio to return [], then it will just get stuck in the infinite while loop.

Supressing that two lines prints me this error, when i click on it, the same as before:

It’s because listar_roms_en_directorio returns [] from whichever directory it’s being run from (e.g. somewhere in which roms has no files with those extensions, if the directory exists at all).

Suprressing the line:

    roms = [archivo for archivo in archivos if archivo.lower().endswith((".sfc", ".smc"))]

makes my that error again:

But when i run this command:

python3 reader.py

Its appears me this:

Which works correctly, but idk what happens when i click on it…

EDIT:

import subprocess
while True:
    subprocess.run(["zsnesw.exe","smw.smc"])

Cant make the rom running via clicking on it…

Again, your code has a relative file path to zsnesw.exe in it, not an absolute one, so it can only work when run from the correct directory (if it works at all).

And… how to execute that commands in a relative path?

Tl;dr: Don’t

If you want the script to run in an environment neither you nor your users control, e.g. double clicking a python file in File Explorer, or from within what ever environment auto-py-to-exe creates, you cannot assume within those environments that relative file paths will resolve the same as they do when a python file is launched from python via cmd.exe (as you don’t know what absolute file path in the environment they will be resolved w.r.t.)

If the script’s just for you, it’s not best practise but there’s little harm in hard coding an absolute path (use an r-string for this on Windows).

If the script is for other people as well, it’s best to provide a method of configuring where exactly on the user’s machine the executable actually is, and where the files the user can choose from actually are.

I found the solution!!!:

import os
import subprocess

# Rutas a los archivos zsnesw.exe y smw.smc
dirname = os.path.dirname(__file__)
zsnes_path = filename = os.path.join(dirname, "zsnesw.exe")

while True:
    rom_path = filename = os.path.join(dirname, input())

    # Ejecuta zsnesw.exe con el ROM especificado y captura la salida de errores
    result = subprocess.run([zsnes_path, rom_path], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    # Imprime la salida de errores
    print(result.stderr.decode("utf-8"))

Well done!

It’s a good idea to avoid shell=True unless absolutely necessary, by the way.

I improved it again, showing a list of the directory files:

import os
import subprocess

# Rutas a los archivos zsnesw.exe y smw.smc
dirname = os.path.dirname(__file__)
zsnes_path = filename = os.path.join(dirname, "zsnesw.exe")

# Lista todos los archivos en el directorio
archivos = os.listdir(dirname)

# Imprime los nombres de los archivos
for archivo in archivos:
    print(archivo)

while True:
    rom_path = filename = os.path.join(dirname, input())

    # Ejecuta zsnesw.exe con el ROM especificado y captura la salida de errores
    result = subprocess.run([zsnes_path, rom_path], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    # Imprime la salida de errores
    print(result.stderr.decode("utf-8"))