Processpoolexecutor, открывающий несколько окон графического интерфейса - PullRequest
1 голос
/ 27 октября 2019

Я пишу программу для копирования файлов из одного места в другое. Чтобы ускорить процесс, я использовал processpoolexecutor и отправил задания, используя shutil.copy2 для копирования файлов. Моя программа имеет графический интерфейс, и когда я запускаю ее, открывается несколько окон графического интерфейса.

Есть ли способ предотвратить это?

file 1

import Copy_file
import tkinter as tk
from tkinter import filedialog
from tkinter import ttk
from PIL import ImageTk, Image
import threading

# setup window
window = tk.Tk()
window.title("Simple File Backup")
window.resizable(False, False)
window.iconbitmap("Images\\Icon.ico")

class main_window:
    def __init__(self, root):
        # create global variable
        self.source_dialog_selected_directory = tk.StringVar()
        self.destination_dialog_selected_directory = tk.StringVar()

        # initialise other program
        self.copy = Copy_file.copy_file()

        # configure styles
        self.s = ttk.Style()
        self.s.configure("TButton", font=("Humanst521 BT", 15))
        self.s.configure("main.TLabel", font=("Humanst521 BT", 10))
        self.s.configure("title.TLabel", font=("Humanst521 BT", 19))
        self.s.configure("browse.TButton", font=("Humanst521_BT", 8))

        # create frames
        self.main_frame = ttk.Frame(root, padding=10)
        self.main_frame.grid()

        self.top_frame = ttk.Frame(self.main_frame)
        self.top_frame.grid(row=0)

        self.extra_frame = ttk.Frame(self.main_frame)
        self.extra_frame.grid(row=1)

        # add logo
        self.logo = Image.open("Images\\Icon.png")
        self.logo = self.logo.resize((50, 50), Image.ANTIALIAS)
        self.logo = ImageTk.PhotoImage(self.logo)
        self.show_logo = tk.Label(self.top_frame, image=self.logo, relief="sunken")
        self.show_logo.image = self.logo
        self.show_logo.grid(row=0, column=1, columnspan=2, sticky="e", pady=3)

        # title
        ttk.Label(self.top_frame, text="Simple File Backup", style="title.TLabel").grid(row=0, column=0, columnspan=2)

        # create main layout
        ttk.Label(self.top_frame, text="Source Directory: ", style="main.TLabel").grid(row=1, column=0, pady=3)

        self.source_directory = ttk.Entry(self.top_frame, width=30,
                                          textvariable=(self.source_dialog_selected_directory if not self.source_dialog_selected_directory == "" else None))
        self.source_directory.grid(row=1, column=1, pady=1)

        ttk.Label(self.top_frame, text="Destination Directory: ", style="main.TLabel").grid(row=2, column=0, pady=3)

        self.destination_directory = ttk.Entry(self.top_frame, width=30,
                                               textvariable=(self.destination_dialog_selected_directory if not self.destination_dialog_selected_directory == "" else None))
        self.destination_directory.grid(row=2, column=1, pady=3)

        # open file explorer buttons
        self.source_browse = ttk.Button(self.top_frame, text="---", width=4, style="browse.TButton",
                                        command=lambda:self.source_dialog())
        self.source_browse.grid(row=1, column=2, sticky="ns", padx=2)

        self.destination_browse = ttk.Button(self.top_frame, text="---", width=4, style="browse.TButton",
                                             command=lambda:self.destination_dialog())
        self.destination_browse.grid(row=2, column=2, sticky="ns", padx=2)

        # copy button
        self.copy_button = ttk.Button(self.top_frame, text="Copy", style="TButton", command=lambda:self.start())
        self.copy_button.grid(row=3, column=0, columnspan=3, pady=5)

        # extra items layout
        self.progress_bar = ttk.Progressbar(self.extra_frame, orient="horizontal", length=350, value=0)
        self.progress_bar.pack(side="top")

        self.output_box = tk.Text(self.extra_frame, takefocus=0, width=50, height=15, font=("Humanst521_BT", 10))
        self.output_box.pack(side="left", pady=5, padx=5)#, sticky="nsew")

        self.scrollbar = ttk.Scrollbar(self.extra_frame)
        self.scrollbar.pack(fill="y", side="right")
        self.scrollbar.config(command=self.output_box.yview)
        self.output_box.config(yscrollcommand=self.scrollbar.set)

    def start(self):
        self.reset_progressbar()
        self.update_progressbar()
        self.reset_output()
        copy_thread = threading.Thread(target=self.copy.main_copy, args=(self.get_contents(self.source_directory),
                                                                              self.get_contents(self.destination_directory)))
        copy_thread.start()
        output_thread = threading.Thread(target=self.update_output, args=())
        output_thread.start()

    def reset_output(self):
        self.output_box.delete(1.0, tk.END)

    def update_output(self):
        self.output_box_split = ""
        while self.copy.finished == False:
            if not self.copy.output == "":
                self.output_box.insert(tk.END, self.copy.output)
                self.output_box.insert(tk.END, "---------------------\n")
                self.copy.output = ""

    def reset_progressbar(self):
        self.progress_bar["value"] = 0

    def update_progressbar(self):
        if not self.progress_bar["value"] == 100.0:
            self.progress_bar["value"] = self.copy.current_progress()
            print(self.copy.current_progress())
            window.after(500, self.update_progressbar)

    def source_dialog(self):
        self.source_dialog_selected_directory.set(filedialog.askdirectory(title="Select source directory"))
        print(self.source_dialog_selected_directory.get())

    def destination_dialog(self):
        self.destination_dialog_selected_directory.set(filedialog.askdirectory(title="Select destination directory"))
        print(self.destination_dialog_selected_directory.get())

    def get_contents(self, object):
        self.output = object.get()
        return self.output


# run main_window class with root at tkinter window
main_window(window)

# main gui loop
tk.mainloop()

file2, называется Copy_file.py. Проблема в функции copy ()

import os, shutil, threading
from time import sleep
from concurrent.futures import ProcessPoolExecutor

class copy_file():
    def __init__(self):
        self.file_bytes_copied = 0
        self.full_directory_size = 0
        self.output = ""
        self.finished = False
        self.jobs = {}

    def get_directory_size(self, directory):
        total_size = 0
        for dir, subdir, file in os.walk(directory):
            for x in range(len(file)):
                total_size += os.stat(dir + "\\" + file[x]).st_size
        return total_size

    def current_progress(self):
        if self.file_bytes_copied > 0 and self.full_directory_size > 0:
            progress = (self.file_bytes_copied/self.full_directory_size)*100
            progress = round(progress, 2)
            return progress

    def concatenate_file_modification(self, path):
        name = os.path.basename(path)
        name = name.split(".")
        mod_time = str(os.stat(path).st_mtime)
        mod_time = mod_time.replace(".", "-")
        concatenate = name[0]+" "+mod_time+"."+name[1]
        return concatenate

    def copy(self):
        with ProcessPoolExecutor(max_workers=3) as executor:
            for src, dst in self.jobs.items():
                self.output = src + " wasn't found in destination, creating copy...\n"
                sleep(0.001)
                executor.submit(shutil.copy2, src, dst)

    def main_copy(self, source, destination):
        self.finished = False
        self.file_bytes_copied = 0
        self.full_directory_size = self.get_directory_size(source)

        self.file_bytes_copied = 0.01
        for self.root_dir, self.sub_dir, self.file in os.walk(source):
            # remove the first part of the source, leaving the relative directory of the files within the source
            self.root_dir = self.root_dir[len(source):]

            # create current directory variable
            self.current_directory = destination+self.root_dir

            # iterate through sub-directories
            for y in range(len(self.sub_dir)):
                # check if directory exists, if not create it
                if not os.path.isdir(self.current_directory+"\\"+self.sub_dir[y]):
                    self.output = self.current_directory+"\\"+self.sub_dir[y] + " wasn't found in destination, creating...\n"
                    os.mkdir(self.current_directory+"\\"+self.sub_dir[y])
                    sleep(0.001)
                else:
                    self.output = self.current_directory + "\\" + self.sub_dir[y] + " was found in destination, no action taken\n"
                    sleep(0.001)

            # iterate through files
            for self.i in range(len(self.file)):
                # get the file directory to search for
                self.file_to_search = self.current_directory+"\\"+self.concatenate_file_modification(source+self.root_dir+"\\"+self.file[self.i])

                # check if path exists, if not copy across file
                if not os.path.exists(self.file_to_search):
                    self.jobs[source + self.root_dir + "\\" + self.file[self.i]] = self.file_to_search

                # if file does exist, print no action taken
                elif os.path.exists(self.file_to_search):
                    self.output = self.file_to_search + " was found in destination, no action taken\n"
                    sleep(0.001)

                # update file_bytes_copied to current progress
                self.file_bytes_copied += os.stat(source + self.root_dir + "\\" + self.file[self.i]).st_size
        self.copy()
        #print(self.jobs)
        self.finished = True
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...