python tkinter+threading/multiprocessing

Наверняка этот вопрос несколько вас смутит, так как скорее всего я ходил вокруг да около решения.

(принципиальной разницы в Python отсутствует, просто я пользуюсь Python 3.9)

Суть программы:

Tkinter окно предлагает выбрать из списка элемент для скачивания. После пользователь выбирает и начинается процесс скачивания и разархивации в Х-директорию. Это было организованно импортом из installer mn функцию (в прикрепленном коде видно).

Но нужно признать, что при вызове этой функции (на прямую, без threading) GUI Tkinter останавливается, так как происходит requests.get (в функции mn() модуля installer.

Сам вопрос:

  1. решено - спасибо, Сергей Шашко!.
  2. Как по нажатию button1 запустить threading.Thread(target=installer).start (но я находил ответы в которых говорилось что лучше использовать multiprocessing).

Прилагаю код главного процесса:

import subprocess
import threading
from tkinter import *
#import os
#import asyncio
from installer import mn


res_packs = ['one','two']


def install(): #вызывается нажатием button1
    global ins_lbl
    try:
        mn(listbox1.selection_get()) #функия для начала скачивания

                try:
                    ins_lbl.destroy()

                except NameError:
                    pass

                ins_lbl = Label(root,text='Установка',fg='white',bg='black')
                ins_lbl.place(x=10,y=70)


            except TclError:
                try:
                    ins_lbl.destroy()
                except NameError:
                    pass

                ins_lbl = Label(root, text='Выбери!', fg='white', bg='red')
                ins_lbl.place(x=10, y=70)
        
        #GUI
        root = Tk()
        root.overrideredirect(True)
        root['bg'] = 'black'
        root.geometry('200x130+890+200')
        root.resizable(False,False)
        
        listbox1 = Listbox(root,height=5,width=15,selectmode=EXTENDED,selectbackground='#0d0d26',background='black',fg='red',selectforeground='red',activestyle='none')
        listbox1.place(x=100,y=5)
        for i in res_packs:
            listbox1.insert(END,i)
        
        thr = threading.Thread(target=install) #preinit
        not_suc_lbl = Label(root) #preinit
        suc_lbl = Label(root) #preinit
    
        button1 = Button(root,text='Установить',width=10,height=2,bg='#0d0d26',fg='red',bd=5,activebackground='#202042',activeforeground='white',command=thr.start) #кнопка что активирует install() функцию. --- проблема. если убрать threads и просто вызвать install, то GUI останавливается.
        button1.place(x=10,y=10)
    
        button2 = Button(root,text='Выход',width=5,height=1,bg='#0d0d26',fg='red',bd=5,activebackground='#202042',activeforeground='white',command=exit)
        button2.place(x=75,y=95)
    
        root.mainloop()

Так же код py файла, функция из которого вызывается при нажатии button1:

from os import system, remove
from sys import argv
from zipfile import ZipFile
from requests import get
from ctypes import windll


def mn(name):
    try:
        print('Start load')
        file = get(f'https://example.it/{name}.zip').content

        with open('file.zip','wb') as f:
            f.write(file)
        print('Success!')

        with ZipFile('file.zip','r') as f:
            print('Extracting')
            f.extractall()

        print('Success!')
        remove('file.zip')


    except Exception as error: #создания окна с ошибкой.
        answer = windll.user32.MessageBoxW(0,f"ERROR: {str(error)}","ERROR", 5)

        if answer == 4:
            system('cls')
            main()
        else:
            pass

Так же прилагаю фото самого окна, ежели вдруг нужно будет посмотреть графику (хотя я не думаю что это нужно..)

window Tkinter GUI


Ответы (1 шт):

Автор решения: NoneType

Чт.. ответ был очевиден... достаточно было просто создать ещё одну функцию, и вней создавать каждый раз новый поток... Вопрос решен, итоговый код:

import threading
from tkinter import *
import os
import requests
from zipfile import ZipFile
from ctypes import windll


res_packs = [1,2]


def mn(fl):
    threading.Thread(target=main,args=[fl]).start()


def main(name):
    try:
        print('Start load...')
        file = requests.get(f'https://{name}.zip').content
        with open('file.zip','wb') as f:
            f.write(file)
        print('Success!.')
        with ZipFile('file.zip','r') as f:
            print('Extracting...')
            f.extractall()
        print('Success!.')
        os.remove('file.zip')
    except Exception as error:
        answer = windll.user32.MessageBoxW(0,f"ERROR: {str(error)}","----------ERROR----------", 5)
        if answer == 4:
            os.system('cls')
            mn(name)
        else:
            pass

def install():
    global ins_lbl
    try:
        mn(listbox1.selection_get())
        try:
            ins_lbl.destroy()
        except NameError:
            pass
        ins_lbl = Label(root,text='Установка..',fg='white',bg='black')
        ins_lbl.place(x=10,y=70)
    except TclError:
        try:
            ins_lbl.destroy()
        except NameError:
            pass
        ins_lbl = Label(root, text='Выбери!', fg='white', bg='red')
        ins_lbl.place(x=10, y=70)


root = Tk()
root.overrideredirect(True)
root['bg'] = 'black'
root.geometry('200x130+890+200')
root.resizable(True,True)

listbox1 = Listbox(root,height=5,width=15,selectmode=SINGLE,selectbackground='#0d0d26',background='black',fg='red',selectforeground='red',activestyle='none')
listbox1.place(x=100,y=5)
for i in res_packs:
    listbox1.insert(END,i)


not_suc_lbl = Label(root)
suc_lbl = Label(root)
button1 = Button(root,text='Установить',width=10,height=2,bg='#0d0d26',fg='red',bd=5,activebackground='#202042',activeforeground='white',command=install)#thr.start)
button1.place(x=10,y=10)
button2 = Button(root,text='Выход',width=5,height=1,bg='#0d0d26',fg='red',bd=5,activebackground='#202042',activeforeground='white',command=exit)
button2.place(x=75,y=95)
root.mainloop()

Код вроде как работает, спасибо за помощь!

→ Ссылка