how to implement saving? - python

I need to make the button save the path to its application. That is, I bind, say, a shortcut to a button, everything works, but if I restart, everything needs to be done again. Please tell me how to implement saving?
my code:
import tkinter.filedialog as tfd
import tkinter as tk
import os
window = tk.Tk()
window.title("Мой Открыватель")
window.geometry("600x400")
window.resizable(False, False)
file_name = ""
def open():
global file_name
if file_name == "":
file_name = tfd.askopenfilename()
os.startfile(file_name)
else:
os.startfile(file_name)
if btn1["text"] == "":
btn1["text"] = file_name
btn1 = tk.Button(window, text="", command=open)
btn1.place(x = 20, y = 25)
window.mainloop()

You can save data in many different ways. Three such ways are:
Use a database, for example sqlite to store your data. Fetch your data when the program starts and populate the required fields. -> https://docs.python.org/3/library/sqlite3.html
Serialize your data with the use of pickle -> https://docs.python.org/3/library/pickle.html (Please note, pickle is not secure)
Use a .txt, .csv or other types of files. Write your data to the file, then when your program starts, load the data from the file.

Related

Trying to call a global variable in another function and getting NameError:

First time poster, new to Python, so be easy on me. Also apologize for any formatting faux pas as again, I'm new here.
I'm writing a Python script to parse through a .csv and transfer the necessary information into a .xml format, and I'm trying to make it so that the end-user can select the .csv they want to use rather than having to actually open the code and copy/paste a filepath into the function.
I've got a basic GUI going with the tkinter module and I've got a function that opens a filedialog and allows the user to select a file.
From what I understand in what I've written, this function returns a filepath as a TextIO wrapper object that I'm then converting to a string, trimming down, and trying to store in a global variable for use in the function that will actually run the "conversion"; however, I am running into a NameError in the next function that says my variable is not defined.
Output is:
line 45, in <module>
with open(imported_csv, newline='') as csv:
NameError: name 'imported_csv' is not defined. Did you mean: 'import_csv'?
For now, I'm just trying to get the function to read the csv and output the data to the terminal so I can make sure that the function is actually reading the csv before I go any further.
I'm sure I'm just missing something really basic, but I may be going about this totally the wrong way. Please help! Code follows below:
`
import csv
from tkinter import *
from tkinter import filedialog
# from tkinter import ttk #<---for styles
### ~GUI code~ ###
## static GUI elements
root = Tk()
root.title("CSV to XML converter for Command camera servers")
root.geometry('1200x600')
subtitle = Label(root, text = "Select a csv to import:")
subtitle.grid(column=0, row=0)
## interactive GUI elements
def converting_text():
subtitle.configure(text = 'Converting, please wait...')
convert_button.configure(fg = 'grey')
convert_button = Button(root, text = "Convert Now", command = lambda: [converting_text(), conversion()])
convert_button.grid(column=1, row=7)
### import csv
selected_csv = Label(text = '')
selected_csv.grid(column=2, row=1)
def import_csv():
global imported_csv
imported_csv = filedialog.askopenfilename() #opens dialog window to select a file
imported_csv = open(imported_csv, 'r') #retrieves filepath from dialog
imported_csv = str(imported_csv) #converts filepath to a string
selected_csv.configure(text = imported_csv.lstrip("<_io.TextIOWrapper name=").rstrip(" mode='r' encoding='cp1252'>") + "'") #trims unnecessary chars from filepath
return imported_csv
choose_file_button = Button(root, text = "Browse files", command = import_csv)
choose_file_button.grid(column=1, row=2)
## ~conversion function code~ ##
with open(imported_csv, newline='') as csv:
def conversion():
csvread = csv.reader(csv, delimiter=',')
for row in csvread:
print(', '.join(row))
root.mainloop()
`

How do I open a file with tkinter and save the data to another variable?

I am learning to use tkinter and I cannot figure out how to open a text file and save the data so that I can use the data in other calculations. In my code below a button is created that when pressed asks for and opens a file. It then prints the content of the file in the console. If the file contains for example a single number, say 100, I can't figure out how to save that number as a variable like "a."
from tkinter.filedialog import askopenfile
root = Tk()
root.geometry('200x100')
# This function will be used to open
# file in read mode and only Python files
# will be opened
def open_file():
file = askopenfile(parent=root, filetypes =[('Text Files', '*.txt')])
if file is not None:
content = file.read()
print(content)
a = content
btn = Button(root, text ='Open', command = lambda:open_file())
btn.pack(side = TOP, pady = 10)
You are assigning the contents of the file to a variable declared within the function. It will be destroyed after the function finishes.
Declare the variable before the function
data = []
Append the content of the file to the container value within the function
def open_file(container):
file = askopenfile(parent=root, filetypes =[('Text Files', '*.txt')])
if file is not None:
content = file.read()
print(content)
# give the content to the data
data.append(content)
However if you are going to give the data to another widget using a instance of tk.StringVar() might be better as most widgets have a textvariable option.
data = StringVar()
And instead of appending StringVar uses the set() method.
data.set(content)
Resources for you:
https://www.pythontutorial.net/tkinter/tkinterstringvar/
And:https://www.delftstack.com/howto/python-tkinter/how-to-change-the-tkinter-button-text/

How to save all my Treeview's data and also specific data in different Excel files?

I'm trying to save my treeview's data in different Excel files, actually my code is working UPDATING my data in the same Excel file every time I want to save it, so What I want is to save in different files. I mean when I push my save button it shows 'where I want to save it in my computer' also 'what name to give that file', then just show a message 'saved successfully' or just 'You didn't select any data for saving'. This is my code which is saving the data in the same file:
def save():
cols = ['ID CARD','NAME','SURNAME', 'DATE']
path = 'read.csv'
excel_name = 'newfile.xlsx'
lst = []
with open(path, "w", newline='') as myfile:
csvwriter = csv.writer(myfile, delimiter=',')
for row_id in mytree.get_children():
row = mytree.item(row_id,'values')
lst.append(row)
lst = list(map(list,lst))
lst.insert(0,cols)
for row in lst:
csvwriter.writerow(row)
writer = pd.ExcelWriter(excel_name)
df = pd.read_csv(path)
df.to_excel(writer,'sheetname')
writer.save()
It wouldnt be so hard to do this, you have to use filedialog from tkinter:
from tkinter import filedialog, messagebox
and then replace excel_name with:
excel_name = filedialog.asksaveasfilename(title='Save location',defaultextension=[('Excel','*.xlsx')],filetypes=[('Excel','*.xlsx')])
This should bring up a file dialog asking you a location to save the file, after which the logic saves the file on the returned location. You can make this more better with messagebox, like:
excel_name = filedialog.asksaveasfilename(title='Save location',defaultextension=[('Excel','*.xlsx')],filetypes=[('Excel','*.xlsx')])
if not excel_name or excel_name == '/': # If the user closes the dialog without choosing location
messagebox.showerror('Error','Choose a location to save')
return # Stop the function
Though I am not sure on if excel_name will be '' or '/' everytime the user closes, use print(excel_name) and close the box and then make the if with whatever is printed out.
More about filedialog with tkinter: Tkinter Dialogs — Python 3.9.2 documentation

At wits end trying to make .exe

Python 3.65, windows 7.
I am at my wits end. I've spent the last 2 weeks learning python from scratch. I just want to make small system utils and I finally made a little program and it simply will not run as a stand alone .exe file.
I have spent the last 2 days trying every suggestion I can find and nothing works. For me there is no point in investing all this time and hassle if I can't make executables.
What I am asking is can some kind person try to compile this on their windows machine and see if it's just me (or my computer Windows 7 64bit) that is the problem. I have read somewhere there are problems with win 7 with some exes.
If that's not possible could someone look at the code and see if there is anything obvious that might cause compile problems?
I have tried cx_freeze and pyinstaller. they make the exes. They run, show a dos box and then nothing.
I have even tried down-grading as far as python 2.7 and I am just in a right mess I don't know what else to do. I have really enjoyed learning Python and I have to get this sorted before continuing and it's driving me crazy, please help.
Steve.
import pyperclip
from tkinter import *
from ctypes import windll
import os
import time
#default folder for saves "c:\\cb-pastes"
#default txt file "c:\\cb-pastes\\saved.txt"
#================set up gui=======================
root = Tk()
#check if "c:\\cb-pastes" exists, if not, create folder
check_folder=os.path.isdir("c:\\cb-pastes")
if not check_folder:
os.makedirs("c:\\cb-pastes")
#button functions
def call_save():
ct=time.asctime() #get system time and date in ct
cb_txt = pyperclip.paste() #store clipboard in cb_txt
f = open("c:\\cb-pastes\\saved.txt","a") # open the file:
f.write ("\n") #newline
f.write (ct) #save date and time
f.write ("\n")
f.write (cb_txt) #append to text file
f.write ("\n")
f.write ("-----------------------------")
f.close() #Close the file
def call_clear(): #clear clipboard
if windll.user32.OpenClipboard(None):
windll.user32.EmptyClipboard()
windll.user32.CloseClipboard()
def call_view(): #open text file of saved clips
os.startfile('c:\\cb-pastes\\saved.txt')
def call_viewcb(): #open text file of current clipboard contents
cb_get = pyperclip.paste()
f = open("c:\\cb-pastes\\temp.txt","w")
f.write (cb_get)
f.close()
os.startfile('c:\\cb-pastes\\temp.txt')
#create window
root.title ("CBMan V0.7")
root.geometry ("230x132")
# create buttons
app = Frame(root)
app.grid()
button1 = Button(app, text = "Save Clipboard", command=call_save)
button1.grid(row=0,column=0)
button2 = Button(app, text = "Clear Clipboard", command=call_clear)
button2.grid()
button3 = Button(app, text = "View Saves ", command=call_view)
button3.grid()
button4 = Button(app, text = "View Clipboard ", command=call_viewcb)
button4.grid()
#insert logo
photo = PhotoImage(file="c:\\cb-pastes\\cbman.gif")
label = Label(image=photo)
label.image = photo # keep a reference!
label.grid(row=0,column=1)

save as file dialog - how to not allow overwrite

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?
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)
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'),)
)
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)
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")

Categories