Tkinter window 以防止 PermissionError

Tkinter window to prevent PermissionError

我正在创建一个脚本,该脚本将收集数据并将其写入 spreadsheet 使用 openpyxl。尝试在工作簿打开时保存它会导致 permissionError 并从剪贴板中删除所有内容而不保存文档。

由于脚本的执行时间很长,如果使用它的人让工作簿保持打开状态,那将是一件非常令人头疼的事情。为了防止这种情况,我正在尝试实现一个 tkinter window,它将告诉用户在出现 permissionError 时关闭 excel sheet 并保持打开状态直到他们关闭。

我想我把它弄得有点过于复杂了,而且我知道这不是解决这个问题的最佳方法。我真的很感激任何关于如何以正确的方式做到这一点的提示。这是我现在拥有的代码:

import openpyxl as op
import tkinter

class warning:
    def __init__(self, root):
        self.root = root
        self.root.title('WARNING')
        self.text = tkinter.Label(root, text = 'Please close spreadsheet, then press "Ok" to proceed.' )
        self.text.grid(row = 1)
        self.frame = tkinter.Frame(root)
        self.button = tkinter.Button(self.frame, text = 'Ok', command = tryToSave(book, 'companies.xlsx')).grid(row = 2, column = 0)
        self.frame.grid(row = 2)

    def close(self):
        self.root.destroy()

def tryToSave(book, name):
    message = tkinter.Tk()
    functionality = warning(message)
    try:
        book.save(name)
        functionality.close()
    except PermissionError:
        message.mainloop()
        tryToSave(book, name)



book = op.load_workbook('C://Users/Alec/envs/RoboEmily/companies.xlsx')
tryToSave(book, 'C://Users/Alec/envs/RoboEmily/companies.xlsx')

所以我能想到的唯一方法"automatic"检查文件是否关闭的方法是输出任务管理器的内容和解析以查看文件是否打开,但这似乎非常低效且考虑不周。

更好的解决方案(主观上来说)是使用 tkinter 的 Toplevel 小部件并让用户尝试从 Toplevel 再次 运行 "Save" 函数,如果它最初失败了。

我创建了一个示例,您可以在下面查看:

from tkinter import *

class App:
    def __init__(self, root):
        self.root = root

        #Below we declare the "message window"
        self.top = Toplevel(self.root) #this creates the window
        self.top.withdraw() #this hides the window
        self.toplabel = Label(self.top, text="File is already open, please close first") #label for the window
        self.topsave = Button(self.top, text="Save", command=self.save) #button for the window

        #packing widgets for the toplevel
        self.toplabel.pack()
        self.topsave.pack()

        self.button = Button(self.root, text="Save", command=self.save)
        self.button.pack()

    def save(self):
        try:
            with open("file.csv", "w") as f: #we open the file pythonically
                f.write("Lorem ipsum") #we attempt to write to the file
                self.top.withdraw() #we attempt to hide the top level window
        except PermissionError:
            self.top.deiconify() #if we get a PermissionError exception, we try and unhide the window

root = Tk()
App(root)
root.mainloop()

这将创建一个带有保存按钮的 window。按下此按钮后,打开文件并尝试保存到其中。如果保存失败,那么我们取消隐藏我们之前创建的 window,它也有一个保存按钮。按下此保存按钮后,我们 运行 具有相同的功能(打开文件、尝试保存、取消隐藏 window)。如果该功能再次失败,对用户来说没有明显的变化。如果函数成功,则文件被保存到 Toplevel window 再次隐藏自己。

我想我想多了。创建 class 似乎有点矫枉过正。我已经将原始代码重写为一个更简单的函数。

import openpyxl as op
import tkinter       

def tryToSave(book, name):
    while 1:
        try:
            book.save(name)
            break
        except PermissionError:
            root = tkinter.Tk()
            message = tkinter.Label(root, text = 'Please close spreadsheet and click "ok"')
            message.grid(row = 1)

            ok = tkinter.Button(root, text = 'Ok', command = root.destroy).grid(row = 2)
            message.mainloop()

book = op.load_workbook('C://Users/Alec/envs/RoboEmily/companies.xlsx')
tryToSave(book, 'C://Users/Alec/envs/RoboEmily/companies.xlsx')

这将创建一个 tkinter window 指示用户关闭价差sheet 并将持续到价差sheet 关闭并且用户单击 'ok'按钮。如果他们在关闭 sheet 之前单击该按钮,window 将被销毁并立即重新创建。