python tkinter+threading/multiprocessing
Наверняка этот вопрос несколько вас смутит, так как скорее всего я ходил вокруг да около решения.
(принципиальной разницы в Python отсутствует, просто я пользуюсь Python 3.9)
Суть программы:
Tkinter окно предлагает выбрать из списка элемент для скачивания. После пользователь выбирает и начинается процесс скачивания и разархивации в Х-директорию. Это было организованно импортом из installer mn функцию (в прикрепленном коде видно).
Но нужно признать, что при вызове этой функции (на прямую, без threading) GUI Tkinter останавливается, так как происходит requests.get (в функции mn() модуля installer.
Сам вопрос:
решено- спасибо, Сергей Шашко!.- Как по нажатию
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
Так же прилагаю фото самого окна, ежели вдруг нужно будет посмотреть графику (хотя я не думаю что это нужно..)
Ответы (1 шт):
Чт.. ответ был очевиден... достаточно было просто создать ещё одну функцию, и вней создавать каждый раз новый поток... Вопрос решен, итоговый код:
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()
Код вроде как работает, спасибо за помощь!
