0

Cuando ejecuto mi aplicación se ejecuta muy bien, después de hacer el .exe voy a mi carpeta dist y haga doble clic en el .exe y luego cuando intento cerrar mi aplicación, aparece 5 veces más y si se cierra cualquier otro aparece 5 veces más y así sucesivamente.

Pensaba que podía ser la herramienta de PyIstaller así que decidí utilizar otra herramienta que genera los .exe y utilicé cx_Freeze y me dio el mismo resultado, ademas de que ya he intentado hacerlo en Widows 7 y en Windows 10 y no logro resolverlo, no se en que ciclo infinito se este metiendo o no se que es lo que sucede

Adjunto imagen :

introducir la descripción de la imagen aquí

Estoy usando Python 3.6 y Firebase 1.2

main.py
from tkinter import *
from conexion_firebase import ConexionFirebase

root = Tk()
#Variables
palabraClave = StringVar(value="cuidaremos")
leerEntry = StringVar()
agregarPalabraClave = StringVar()
#Errores
error = StringVar()
error2 = StringVar()
#Exitosos
exito = StringVar()
exito2 = StringVar()

conectar = ConexionFirebase()

#funciones
def enviarPalabra():
    exito2.set("")
    error2.set("")
    if agregarPalabraClave.get() == "":
        error2.set("Agrega un valor")
    elif len(agregarPalabraClave.get()) < 3:
        error2.set("Agrega una palabra que tenga mas de 3 letras")
    else:
        if conectar.agregarDatos(agregarPalabraClave.get()):
            exito2.set("Palabra {} insertada correctamente".format(agregarPalabraClave.get()))
        else:
            error2.set("Error esa palabra ya existe")
def agregarPalabra():
    global agrega_palabra_entry
    root2 = Toplevel(root)
    Label(root2, text="Agrega una palabra clave").pack()
    Entry(root2, textvar=agregarPalabraClave).pack()
    Label(root2, textvar=exito2).pack()
    Label(root2, textvar=error2).pack()
    Button(root2, text="Agregar", command=enviarPalabra).pack()

def listToString(lista):
    str1 = ""
    for letra in lista:
        str1 += str(letra)

    return str1
def generar():
    error.set("")
    exito.set("")
    if leerEntry.get():
        partirNombre = leerEntry.get().split()
        if len(partirNombre) == 2:
            if len(partirNombre[0])>= 4 and len(partirNombre[1])>= 4:
                nombre, apellido = partirNombre[0][0:4].lower(), partirNombre[1][0:4].lower()
                if not nombre.isalpha() and len(nombre) >= 4:
                    print("EL NOMBRE CON DIGITOS")
                    error.set("El nombre no debe de incluir numeros")

                elif not apellido.isalpha() and len(nombre) >= 4:
                    print("EL apellido CON DIGITOS")
                    error.set("El apellido no debe de incluir numeros")
                else:
                    primeraLetraMayuscula = nombre[0].upper()
                    nombreCompleto = nombre + apellido
                    print(nombreCompleto)
                    palabrasArray = []
                    for letra in nombreCompleto:
                        if letra in palabraClave.get():
                            indice = palabraClave.get().index(letra)
                            if indice == len(palabraClave.get()) - 1:
                                palabrasArray.append(0)
                            else:
                                palabrasArray.append(indice + 1)
                        else:
                            palabrasArray.append(letra)

                    palabrasArray.insert(4,'.')
                    palabrasArray.pop(0)
                    palabrasArray.insert(0, primeraLetraMayuscula)
                    print(palabrasArray)
                    exito.set(listToString(palabrasArray))
            else:
                error.set("Cada palabra debe de tener almenos cuatro letras")
        else:
            error.set("Agrega un nombre y un apellido")
    else:
        error.set("""Agrega un nombre y un apellido
                y un espacio intermedio""")
#menu
menubar = Menu(root)
root.config(menu=menubar)

submenu_1 = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Archivo", menu=submenu_1)
submenu_1.add_command(label="agregar palabra", command=agregarPalabra)

#Labels
Label(root, text="Bienvenidos Al Genereador de Contraseñas").pack()

#Entry
Entry(root, textvar=leerEntry).pack()
Label(root, textvar=error).pack()
Label(root, textvar=exito, font=("sans-serif", "20")).pack()
#Buttons
Button(root, text="Generar", command=generar).pack()

root.mainloop()
conexion_firebase.py
from firebase import firebase

class ConexionFirebase:
    """This class connect with firebase"""
    def __init__(self):
        self.firebase = firebase.FirebaseApplication('https://pythondbgenerator.firebaseio.com/', None)

    def obtenerDatos(self):
        result =  self.firebase.get('/pythondbgenerator/Palabras', None)
        palabras_array = []
        for key, value in result.items():
            palabras_array.append(value['Name'])
        return palabras_array

    def agregarDatos(self, nombre):

        lista_palabras = self.obtenerDatos()

        if nombre in lista_palabras:
            return False
        else:
            datos = {
            'Name':nombre
            }
            result =  self.firebase.post('/pythondbgenerator/Palabras', datos)
            return True
    def eliminarDatos(self, id_dato):

        result = self.firebase.delete('/pythondbgenerator/Palabras', id_dato)
        return result
    def actualizarDatos(self, id_dato, nombre):

        result = self.firebase.put('/pythondbgenerator/Palabras/{}'.format(id_dato), "Name",nombre)
        return result
FJSevilla
  • 55,603
  • 7
  • 35
  • 58

1 Answers1

0

Firebase hace uso de multiprocessing de forma intensiva para trabajar de forma asíncrona.

Por otro lado Windows usa spawn para lanzar el nuevo proceso, en vez de crear una copia idéntica del proceso padre y a partir de ahí bifurcar, inicia un proceso limpio heredando solo una parte imprescindible de los recursos del proceso padre.

Esto implica que el módulo es ejecutado completamente de nuevo, importando todos los módulos de nuevo y ejecutando todo el código a nivel global que exista. Si en este código global tienes el código que lanza los procesos entramos en un ciclo no muy sano...

La solución es proteger tu código para evitar la reentrada en los posible multiprocesos usando if __name__ == "__main__": y multiprocessing.freeze_support:

from multiprocessing import freeze_support
from tkinter import *
from conexion_firebase import ConexionFirebase


#funciones
def enviarPalabra():
    exito2.set("")
    error2.set("")
    if agregarPalabraClave.get() == "":
        error2.set("Agrega un valor")
    elif len(agregarPalabraClave.get()) < 3:
        error2.set("Agrega una palabra que tenga mas de 3 letras")
    else:
        if conectar.agregarDatos(agregarPalabraClave.get()):
            exito2.set("Palabra {} insertada correctamente".format(agregarPalabraClave.get()))
        else:
            error2.set("Error esa palabra ya existe")

def agregarPalabra():
    global agrega_palabra_entry
    root2 = Toplevel(root)
    Label(root2, text="Agrega una palabra clave").pack()
    Entry(root2, textvar=agregarPalabraClave).pack()
    Label(root2, textvar=exito2).pack()
    Label(root2, textvar=error2).pack()
    Button(root2, text="Agregar", command=enviarPalabra).pack()

def listToString(lista):
    str1 = ""
    for letra in lista:
        str1 += str(letra)
    return str1

def generar():
    error.set("")
    exito.set("")
    if leerEntry.get():
        partirNombre = leerEntry.get().split()
        if len(partirNombre) == 2:
            if len(partirNombre[0])>= 4 and len(partirNombre[1])>= 4:
                nombre, apellido = partirNombre[0][0:4].lower(), partirNombre[1][0:4].lower()
                if not nombre.isalpha() and len(nombre) >= 4:
                    print("EL NOMBRE CON DIGITOS")
                    error.set("El nombre no debe de incluir numeros")

                elif not apellido.isalpha() and len(nombre) >= 4:
                    print("EL apellido CON DIGITOS")
                    error.set("El apellido no debe de incluir numeros")
                else:
                    primeraLetraMayuscula = nombre[0].upper()
                    nombreCompleto = nombre + apellido
                    print(nombreCompleto)
                    palabrasArray = []
                    for letra in nombreCompleto:
                        if letra in palabraClave.get():
                            indice = palabraClave.get().index(letra)
                            if indice == len(palabraClave.get()) - 1:
                                palabrasArray.append(0)
                            else:
                                palabrasArray.append(indice + 1)
                        else:
                            palabrasArray.append(letra)

                    palabrasArray.insert(4,'.')
                    palabrasArray.pop(0)
                    palabrasArray.insert(0, primeraLetraMayuscula)
                    print(palabrasArray)
                    exito.set(listToString(palabrasArray))
            else:
                error.set("Cada palabra debe de tener almenos cuatro letras")
        else:
            error.set("Agrega un nombre y un apellido")
    else:
        error.set("""Agrega un nombre y un apellido
                y un espacio intermedio""")


if __name__ == '__main__':
    freeze_support()

    root = Tk()
    #Variables
    palabraClave = StringVar(value="cuidaremos")
    leerEntry = StringVar()
    agregarPalabraClave = StringVar()
    #Errores
    error = StringVar()
    error2 = StringVar()
    #Exitosos
    exito = StringVar()
    exito2 = StringVar()

    conectar = ConexionFirebase()
    #menu
    menubar = Menu(root)
    root.config(menu=menubar)

    submenu_1 = Menu(menubar, tearoff=0)
    menubar.add_cascade(label="Archivo", menu=submenu_1)
    submenu_1.add_command(label="agregar palabra", command=agregarPalabra)

    #Labels
    Label(root, text="Bienvenidos Al Genereador de Contraseñas").pack()

    #Entry
    Entry(root, textvar=leerEntry).pack()
    Label(root, textvar=error).pack()
    Label(root, textvar=exito, font=("sans-serif", "20")).pack()
    #Buttons
    Button(root, text="Generar", command=generar).pack()

    root.mainloop()

Siempre que se use multiprocessing en Windows hay que proteger el código global que trabaje con él con if __name__ == "__main__". Es más, es buena práctica hacer esto siempre.

FJSevilla
  • 55,603
  • 7
  • 35
  • 58
  • Muchas gracias por la ayuda, me funcionó, créeme que voy a investigar mas acerca de eso. A mi en la consola no me marcaba error, por eso no sabia que solución buscar en google pero gracias por ayudarme – Javier Antonio Felix Torres Apr 15 '20 at 20:48