Tkinter's filedialog module provides native Save As dialogs. Use asksaveasfile() when you want Tkinter to return an opened file object, or asksaveasfilename() when you want the selected file path and prefer to open the file yourself.

asksaveasfile() returns an open file object. asksaveasfilename() returns a file path. If the user cancels, test the returned value before trying to save.Import the filedialog module from Tkinter:
import tkinter as tk
from tkinter import filedialog
You can then call:
filedialog.asksaveasfile()
filedialog.asksaveasfilename()
There is no need to import asksaveasfile separately if it is being called through filedialog.
asksaveasfile() displays the Save As dialog and returns an already-opened file object. Its default mode is 'w'.
import tkinter as tk
from tkinter import filedialog
def save_file():
file_obj=filedialog.asksaveasfile(mode='w', defaultextension='.txt', filetypes=[('Text files', '*.txt')], parent=root)
if file_obj:
with file_obj:
file_obj.write('Welcome to plus2net')
root=tk.Tk()
root.geometry('400x200')
root.title('Save File')
tk.Button(root, text='Save File', command=save_file).pack(pady=50)
root.mainloop()
The returned object is ready for writing:
file_obj.write('Welcome to plus2net')
Using the file object as a context manager ensures that it is closed after writing.
asksaveasfilename() returns the selected path instead of opening the file.
import tkinter as tk
from tkinter import filedialog
def save_file():
file_path=filedialog.asksaveasfilename(defaultextension='.txt', filetypes=[('Text files', '*.txt')], parent=root)
if file_path:
with open(file_path, 'w', encoding='utf-8') as file:
file.write('Welcome to plus2net')
root=tk.Tk()
root.geometry('400x200')
tk.Button(root, text='Save', command=save_file).pack(pady=50)
root.mainloop()
This version gives the program explicit control over how the file is opened, including its encoding.
| Feature | asksaveasfile() | asksaveasfilename() |
|---|---|---|
| Returns | Opened file object | Selected file path |
| Cancel | Returns no usable file object | Returns no usable path |
| Default mode | 'w' | No file is opened |
Call open() yourself | No | Yes |
| Choose text encoding explicitly | Less direct | Yes, when calling open() |
| Best when | You want a ready-to-write file object | You want control over file opening and saving |
asksaveasfilename() followed by with open(...) is easier to control because the application can choose encoding, mode and error handling explicitly.The user can close the dialog without selecting a file. Always test the returned value before writing.
file_path=filedialog.asksaveasfilename()
if file_path:
print('Selected:', file_path)
else:
print('Save cancelled.')
file_obj=filedialog.asksaveasfile()
if file_obj:
with file_obj:
file_obj.write('Data')
else:
print('Save cancelled.')
open(file_path, ...) before checking that the user actually selected a path.The filetypes option provides file-type choices in the Save As dialog.
filetypes=[
('Text files', '*.txt'),
('CSV files', '*.csv'),
('All files', '*.*')
]
Use it with:
file_path=filedialog.asksaveasfilename(filetypes=filetypes)
The second value is a file pattern. For example, use:
'*.txt'
rather than:
'.txt'
filetypes affects the file choices shown by the dialog. It does not validate the actual contents of the file.
defaultextension specifies the extension to use when the user does not enter one.
file_path=filedialog.asksaveasfilename(
defaultextension='.txt',
filetypes=[('Text files', '*.txt')]
)
For a CSV file:
file_path=filedialog.asksaveasfilename(
defaultextension='.csv',
filetypes=[('CSV files', '*.csv')]
)
initialfile supplies a suggested filename.
file_path=filedialog.asksaveasfilename(
defaultextension='.txt',
initialfile='notes.txt',
filetypes=[('Text files', '*.txt')]
)
The user can keep or change the suggested name.
initialdir sets the directory shown when the Save As dialog first opens.
from pathlib import Path
file_path=filedialog.asksaveasfilename(
initialdir=str(Path.home()),
defaultextension='.txt'
)
This is more portable than hard-coding a Windows drive such as D:\ or F:\.
If a Windows path is required, a raw string is convenient:
initialdir=r'D:\my_data\my_html'

file_path=filedialog.asksaveasfilename(
title='Save Report',
defaultextension='.txt'
)
The exact appearance and placement of the title depends on the platform's native file dialog.
Use parent=root to associate the Save dialog with the Tkinter window that opened it.
file_path=filedialog.asksaveasfilename(
parent=root,
title='Save File'
)
This improves window ownership and modal behaviour, particularly when an application contains several windows.
The native Save As dialog normally asks the user for confirmation when an existing file would be overwritten.
Tk also provides the confirmoverwrite option:
file_path=filedialog.asksaveasfilename(
defaultextension='.txt',
confirmoverwrite=True
)
The default behaviour is to request overwrite confirmation.
confirmoverwrite=False can allow an existing file to be replaced without the normal warning. Native file-dialog behaviour can also vary by platform.The following example saves everything entered in a Tkinter text-entry example.
import tkinter as tk
from tkinter import filedialog
def save_text():
file_path=filedialog.asksaveasfilename(
parent=root,
title='Save Text',
defaultextension='.txt',
filetypes=[('Text files', '*.txt'), ('All files', '*.*')]
)
if not file_path:
return
text=text_box.get('1.0', 'end-1c')
with open(file_path, 'w', encoding='utf-8') as file:
file.write(text)
status.config(text='File saved.')
root=tk.Tk()
root.geometry('500x350')
root.title('Save Text File')
text_box=tk.Text(root, width=50, height=12)
text_box.pack(padx=10, pady=10)
tk.Button(root, text='Save As', command=save_text).pack(pady=5)
status=tk.Label(root, text='')
status.pack(pady=5)
root.mainloop()
'end-1c' excludes the automatic final newline maintained by the Tkinter Text widget.
When saving text through a returned path, specify an encoding explicitly:
with open(file_path, 'w', encoding='utf-8') as file:
file.write(text)
This makes the file encoding explicit and supports Unicode text consistently.
open() call controls encoding, newline handling and other file-writing options.A valid-looking path does not guarantee that writing will succeed. Permissions, unavailable drives or other file-system problems can raise OSError.
try:
with open(file_path, 'w', encoding='utf-8') as file:
file.write(text)
except OSError as error:
print('Unable to save file:', error)
def save_text():
file_path=filedialog.asksaveasfilename(
parent=root,
title='Save Text',
defaultextension='.txt',
filetypes=[('Text files', '*.txt')]
)
if not file_path:
status.config(text='Save cancelled.')
return
text=text_box.get('1.0', 'end-1c')
try:
with open(file_path, 'w', encoding='utf-8') as file:
file.write(text)
status.config(text='File saved successfully.')
except OSError as error:
status.config(text=f'Unable to save: {error}')
This returns a file object:
file_obj=filedialog.asksaveasfile()
This returns a path:
file_path=filedialog.asksaveasfilename()
This is unnecessary:
file_obj=filedialog.asksaveasfile()
# open(file_obj, 'w') # incorrect idea
file_obj is already an opened file object.
Always check the result:
if not file_path:
return
Prefer:
('Text files', '*.txt')
Instead of assuming a drive such as F:\data, use a directory that exists or derive one dynamically.
Use:
defaultextension='.txt'
when the application expects saved files to use a standard extension.
Use a context manager:
with file_obj:
file_obj.write('Data')
or, when opening a returned path:
with open(file_path, 'w', encoding='utf-8') as file:
file.write('Data')
The normal confirmation protects users from accidentally replacing an existing file. Keep it enabled unless the application has another safe overwrite workflow.
The selected filter helps users choose filenames and extensions, but your application must still validate data or file requirements when necessary.
tkinter.filedialog provides native Save As dialogs.asksaveasfile() returns an opened file object.asksaveasfile() is 'w'.asksaveasfilename() returns the selected file path.filetypes with patterns such as *.txt and *.csv.defaultextension to provide a default extension.initialfile to suggest a filename.initialdir to select the directory initially displayed.title to provide a meaningful dialog title.parent=root to associate the dialog with its Tkinter window.confirmoverwrite controls the overwrite-confirmation request, although native behaviour can vary by platform.asksaveasfilename() followed by open() when explicit encoding and file-opening control are required.encoding='utf-8' when writing general Unicode text files.OSError when the application needs to handle file-system write failures.Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.