6

I'm trying to make a savefile dialog in tkinter. I need to save the file name to use later. However, I do not want the filedialog to accept selecting an already existing file name.

So far I only have this:

from tkinter import filedialog

my_file = filedialog.asksaveasfilename(defaultextension = ".myfile", 
                                       filetypes = [("MY SUPER FILE", ".myfile"), 
                                                    ("All files", ".*")])

One possibility would be to get the file name, check if it exists (using os.path.isfile) and ask again the user for new name if there is already a file with the same name. However, the tkinter filedialog asks the user "file already exists. do you want to overwrite?". So it seems confusing if later I tell the user that I do not accept the filename choice. Is there a way to force the tkinter filedialog to not ask the user about the overwriting?

Edit: Based on the suggestions in the answers, I tried to make my own save file dialog.

I basically only added a warning to the tkinter save dialog:

class MySaveFileDialog(filedialog.FileDialog):

""" File save dialog that does not allow overwriting of existing file"""
def ok_command(self):
    file = self.get_selection()
    if os.path.exists(file):
        if os.path.isdir(file):
            self.master.bell()
            return
        messagebox.showarning("The current file name already exists. Please give another name to save your file.")
    else:
        head, tail = os.path.split(file)
        if not os.path.isdir(head):
            self.master.bell()
            return
    self.quit(file)

So, it looks pretty simple. Then I thought: I need to create my own asksaveasfilename function. I went to check the source:

def asksaveasfilename(**options):
"Ask for a filename to save as"

return SaveAs(**options).show()

Humm.. I need to see what is SaveAs doing.

class SaveAs(_Dialog):
    "Ask for a filename to save as"

    command = "tk_getSaveFile"

Aaannddd... i'm lost. I don't understand how this pieces fit together. 'SaveAs' just has the command tk_getSaveFile. How is the SaveFileDialog being used here? And how can I make my own myasksaveasfilename function?

3
  • 1
    Do you really need this? Dialogs with non-standard behaviour are confusing to the user. Also, if the user wants to over-write an existing file it's good to warn them, but it's annoying to actually stop them doing it. So if the selected name matches an existing file, perhaps you can pop up an askokcancel message box to give them one last chance before they shoot themself in the foot. :) Commented Apr 7, 2015 at 13:58
  • @PM 2Ring : I understand your concern. And I would like not to do it this way, but I really need it :) Commented Apr 7, 2015 at 14:04
  • Two things that matters in such problem: 1) has the user an other mean to do it? 2)will it be used voluntarily more often than as a mistake? Here 1) answer is yes (you can delete the file outside the app) and 2) answer depends on what the app does. Commented Apr 7, 2015 at 14:06

4 Answers 4

5
+50

There is no such option. If you want to get rid of the security question, then you'll have to write your own file dialog.

If you look at filedialog.py, you'll see that the dialog is implemented in Python. So all you have to do is to extend the class SaveFileDialog and override the method ok_command() with one that doesn't allow to select an existing file name.

You can use most of the existing code and just change a few texts to achieve your goal.

I haven't tested it but this code should work:

def ok_command(self):
        file = self.get_selection()
        if os.path.exists(file):
            if os.path.isdir(file):
                self.master.bell()
                return
            d = Dialog(self.top,
                       title="Overwrite Existing File",
                       text="You can't overwrite an existing file %r. Please select a new name." % (file,),
                       bitmap='error',
                       default=0,
                       strings=("OK",))
            return
        else:
            head, tail = os.path.split(file)
            if not os.path.isdir(head):
                self.master.bell()
                return
        self.quit(file)
Sign up to request clarification or add additional context in comments.

8 Comments

Note: the file dialog is implemented in python on linux systems. On windows and OSX it is a native file dialog.
@BryanOakley You could make a class inheriting from FileDialog.SaveFileDialog, overwrite the ok_command and call it using fd = MySaveFileDialog(root) filename = fd.go() though right? Although of course that looks nowhere near as pretty as the native OS dialog.
So, from your comments, the asksaveasfilename function does not really use the FileDialog.SaveFileDialog on Windows? But instead gets the OS file dialog? Is that done by the command = "tk_getSaveFile"?
Now I noticed that @Aaron had edited is question a long time ago. And I did not know I could start the filedialog with fd.go() as mentioned by @fhdrsdg.
I'll mark this as the answer and give the bounty, since it led me in the right way to understand how file dialogs are built. Unfortunately, the resulting dialog looks pretty ugly since it does not use the native file dialog from windows.
|
1

An answer to a slightly adjacent topic, but this was the closest existing question on SO so assume others may end up here when faced with the same problem, and I got my answer from above information.

If you are looking to select a tk.filedialog.asksaveasfile, but without overwriting an existing file (ie append to it), and wanting to avoid users being faced with the 'Do you want to overwrite?' popup, one can select the append mode, and turn off the overwrite popup.

    outfilename = tk.filedialog.asksaveasfile(title = 'Save processing output CSV',
                                            initialdir = output_directory,
                                            defaultextension = '.csv', 
                                            mode = 'a',
                                            confirmoverwrite = False,
                                            filetypes = (('csv File', '.csv'),)
                                            )

Comments

0

To complete what Aaron said, here is the current code of ok_command:

def ok_command(self):
        file = self.get_selection()
        if os.path.exists(file):
            if os.path.isdir(file):
                self.master.bell()
                return
            d = Dialog(self.top,
                       title="Overwrite Existing File Question",
                       text="Overwrite existing file %r?" % (file,),
                       bitmap='questhead',
                       default=1,
                       strings=("Yes", "Cancel"))
            if d.num != 0:
                return
        else:
            head, tail = os.path.split(file)
            if not os.path.isdir(head):
                self.master.bell()
                return
        self.quit(file)

Comments

0

You can achieve this using tkFileDialog.asksaveasfilename(confirmoverwrite=False)
Here is a mock up:

import tkFileDialog 
import tkMessageBox as mbox
class Example():
    proceed = False
    while proceed == False:
        dlg = tkFileDialog.asksaveasfilename(confirmoverwrite=False)
        fname = dlg
        if fname != '':
            try:
                f = open(fname, "r")
                f.close()
                mbox.showerror("Error","File exists - Choose another file name")
            except:
                mbox.showinfo("Info","File does not exist - Continue")
                proceed = True
        else:
            break
    print("Finished")

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.