Drop down menu gives PY_VAR0 in txt file - python

I'm working on a little project for my friends and it's with python tkinter.
the code is
def run():
filename = filename_ent.get()
if filename == '':
# to show an error that boxes are empty
messagebox.showerror(
'File exists', 'File already exists, try some other name thas is not used before')
if os.path.exists(f'{filename}.txt'):
# to show an error if the file already exists
messagebox.showerror(
'File exists', 'File already exists, try some other name not used before')
else:
# to open the file for python
new = open(f'{filename}.txt', '+w', encoding='utf-8')
# to write the name and email inside the file
new.write(f'''Day of the week: {clicked}''')
eventl.config(text=f'Done :)!') # to change the label to the name
os.startfile(f'{filename}.txt') # to open the file in a new window
eventl = Label(root, text='What is the name of the event',font=('helvatica',14))
eventl.place(x=0,y=0)
lfilename = Label(root,text="What do you want to call the file?", font = ("helvatica, 14"))
lfilename.pack()
filename_ent = Entry(root)
filename_ent.pack(pady=10,padx=30)
clicked = StringVar()
drop = OptionMenu(root, clicked, "Monday", "Tuesday")
drop.pack(pady=10,padx=10)
b = Button(root, text='Done', command=run)
b.pack(pady=(10, 0))
root.mainloop()
Note: I'm using utf-8 because I'm also using Arabic inputs but that doesn't seem to be the problem since I tried removing it(this isn't the whole code).

It should be new.write(f'''Day of the week: {clicked.get()}''') instead of new.write(f'''Day of the week: {clicked}'''). Clicked is the just the StringVar() you have to access the value of it using the get() method.
Hope this helped, do let me know if any errors.
Cheers

Related

Using SHUTIL to copy a file into a directory with a space in its name

I'm trying to build a program that will read in a list of files, add a prefix and a suffix to the filename, and then copy the file to a new folder with the new file name. So, for example, a file named "Reports.pdf" would become "PBC_Reports_V1.pdf"
The problem I have is when either the source or destination directory have a space in their name, the shutil module can't find the directory. I'm not sure what I need to do to have shutil recognize the directory, and could use some help.
code is as follows:
## This program is intended to allow a batch of files to have their name changed to standard IA formats
import os, shutil, datetime
from tkinter import *
strFolderName = "\Test"
#strNewPath = basePath+strFolderName
root = Tk()
root.title("Bulk File Renaming")
#root.iconbitmap(r"C:\Coding\FlagIcon.bmp")
############################################################################################################################################
## This section sets up the program's GUI. The buttons have to come after the modules, but this has to come at the beginning of the code
## because, of course, putting all the GUI stuff together would make too much sense. Oh well. GUI until the next line of hashtags.
strF = os.getcwd() #Finds the current file path
strFileIn = StringVar() #This is where we'll store the input path
strFileIn.set(strF) #Puts the current directory in the box
strFileOut = StringVar() #This variable is the output path
strFileOut.set(strF+r"\ConvertedFiles")
str1 = StringVar() #This variable holds the radiobutton output, which represents the file prefix
str1.set("\PBC_") #For some reason, if you try to set a variable in the same line you declare it, it stops working.
strPrefixes = [("PBC (Prepared by Client)", "\PBC_"), #A list (tuple?) of the different prefixes and their meaning.
("WP (Working Paper)", "\WP_"), #To be called futher down when we create the radiobuttons
("COM (Communications)", "\COM_"),
("MIN (Minutes)", "\MIN_"),
("PM (Project Management)", "\PM_"),
("DOC (Anything not created by IA or the OPI)", "\DOC_")]
inRow = 5
inCol = 0
for strPref, val in strPrefixes:
Radiobutton(root, text=strPref, variable=str1, value=val).grid(row =inRow, column=inCol, sticky=(W))
inCol=inCol+1
if inCol>2:
inCol=0
inRow=6
#First, labels
myLabelSource = Label(root, text="Source Folder").grid(row=0, column=0, sticky=(E))
myLabelDestn = Label(root, text="Destination Folder").grid(row=1, column=0, sticky=(E))
myLabelPrefix = Label(root, text="Select Desired Prefix").grid(row=3, column=0, sticky=(W))
#Next, input boxes
#Source files' location
enSource = Entry(root, textvariable=strFileIn).grid(row=0, column = 1, columnspan=3, sticky=(W,E))
#Destination files' location
enDestn = Entry(root, textvariable=strFileOut).grid(row=1, column = 1, columnspan =3, sticky=(W,E))
#################################################################################################################################################
#This module shuts down the program
def progExit():
root.quit() #Closes all the program's stuff
root.destroy() #Actually shuts things down.
#This module gets the date the file was last modified
def getDate(strA):
# Depending on how the file was created/modified, the creation date may be placed in the date modified field and vice versa.
# Here, we take both the modified and created date, see which one is earlier, format it in a YYYY-MM-DD format, and
# return it to the user.
strC = os.path.getctime(strA) #Gets the created date, as time since the epoch
strB = os.path.getmtime(strA) #Gets the modified date, as time since the epoch
if strB<strC:
strB = datetime.datetime.fromtimestamp(strB) #Converts the date into a readable string
strB = str(strB)
strB=strB[0:10] #Leaves just the YYYY-MM-DD fields
return strB
else:
strC = datetime.datetime.fromtimestamp(strC)
strC=str(strC)
strC=strC[0:10]
return strC
#This module determines the location of the '.' at the end of the filename, before the file type indicator.
def fileTypeLength(strName):
inI = len(strName)-1 #Since the first letter in the string is in the 0 position, we subtract 1 from the length to make the loop work
while inI>-1:
if strName[inI] == chr(46): #The '.' char has an ascii value of 46. It's easier for python to understand what we're looking for this way.
return inI
else:
inI=inI-1 #We go from the end towards the front so that if there are any '.' in the file name it won't screw up the program
if inI<0:
outputLabel=Label(root, text="Error finding file suffix for file "+strName).grid(row=8, column = 1)
root.quit()
#This module is where the program actually copies the file, and pastes together everything else.
def copyAllFiles():
inA=0
strPrefix=str1.get()
strNewPath=os.path.abspath(strFileOut.get())
strEntry=os.path.abspath(strFileIn.get())
listOfFiles = os.listdir(strFileIn.get())
if os.path.isdir(strNewPath) == False:
os.mkdir(strNewPath)
for entry in listOfFiles:
if os.path.isfile(os.path.join(strEntry, entry)): # Verify that file in question is a file, not a folder
entryEd=entry # entryEd holds the file name
entry=(os.path.join(strEntry, entry)) # entry holds the file location
strDate = getDate(entry) # Gets the file's creation date
inL = len(entryEd)
inS = fileTypeLength(entryEd) #Finds the position of the '.' at the end of the file name
strFT = entryEd[inS:inL] #Here we remove the file type idenifier, so that it can be moved to the end of the copied filename
entryEd=entryEd[0:inS]
strOutputFile = strNewPath+strPrefix+entryEd+"_"+str(strDate)+"_V1"+str(strFT)
shutil.copy2(entry, strOutputFile) #This copies the file, and all its attributes
inA = inA+1
outputLabel=Label(root, text=str(inA)+" files successfully processed").grid(row=8, column = 1)
##### These are the buttons that the GUI uses to launch the program or shut it down.
buttonExit=Button(root, text="Click here to exit", padx=50, command=progExit).grid(row=7, column=2)
buttonProcess=Button(root,text="Rename Files", padx=50, command=copyAllFiles).grid(row=7, column=1)
#The last thing we have to do is name the GUI that we started building on line 9. Tkinter is a funny module.
root.mainloop()
I can verify that the variables have two slashes for all the folder dividers, so `strOutputFile = C:\\Example Folder\\Example Output\\PBC_Reports_V1.pdf' .
Anybody have a suggestion?

why is the location string not showing in the window. tkinter python?

im trying to write a code that will tell you if the location is a file or directory. if its a file, then it will read the file. here is my code (ik its very bad, im sorry)
import os
import tkinter as tk
screen = tk.Tk()
screen.title("files and directories")
screen.geometry("300x100")
def FileDir():
path = location.get(1.0, "end-1c")
location.delete(1.0, tk.END)
if os.path.exists(path):
print("✔ - this location exists")
info_location = tk.Label(screen, text=f"location: {location}")
info_location.pack()
if os.path.isfile(path):
print("\tthis is a file")
type = 'file'
info_type = tk.Label(screen, text=f"type: {type}")
info_type.pack()
while True:
open_file = input("\nDo you want to read this file? ")
if open_file.lower() == 'yes':
with open(path) as file:
contents = file.read()
print(contents)
break
elif open_file.lower() == 'no':
print("goodbye!")
break
else:
print("invalid input")
continue
elif os.path.isdir(path):
print("\tthis is a directory")
type = 'directory'
info_type = tk.Label(screen, text=f"type: {type}")
info_type.pack()
else:
print("✘ - this location doesn't exist")
text = tk.Label(screen, text="Enter file/directory location: ")
text.pack()
location = tk.Text(screen, height = 1, width = 25)
location.pack()
enter_btn = tk.Button(screen, text="Enter", command=FileDir)
enter_btn.pack()
screen.mainloop()
so when putting the location of a string, everything works fine except that the location doesnt show and instead it shows ".!text". anyone know why?
location is a widget rather than a string. The string representation of a tkinter widget is its internal name. Thus, when you do text=f"location: {location}" you are creating a string that contains the name of the widget rather than the contents.
To display the contents you must fetch them from the widget. You're already doing that when you define path, so you just need to use {path} rather than {location}
text=f"location: {path}"

How to make a dropdown list from an existing list in python (pandas and tkinter)

I want the user to submit their csv excel file and choose the columns from a dropdown menu he wants for analysis.
import pandas as pd
import os
import sys
from tkinter import *
root = Tk()
root.title('Eng3')
filepath = input('Enter filepath: ')
assert os.path.exists(filepath), "I did not find the file at, " + str(filepath)
f = open(filepath, 'r+')
print("Hooray we found your file!")
f.close()
file = pd.read_csv(filepath, encoding='latin1', delimiter=',')
column_list = file.columns.tolist()
print(column_list)
So I made the columns names from the excel file into a list. How can I make a dropdown menu from this list(column_list) to show all column names? When I tried:
tkvar = StringVar(column_list)
menu = OptionMenu(root, tvkar, column_list)
I get this error:
AttributeError: 'list' object has no attribute '_root'
I looked around and found this post How can I create a dropdown menu from a List in Tkinter?. Very useful
file = pd.read_csv(filepath, encoding='latin1', delimiter=',')
column_list = file.columns.tolist() #convert pandas dataframe to simple python list
OPTIONS = column_list #this is what solved my problem
master = Tk()
master.title('Eng3')
variable = StringVar(master)
variable.set(OPTIONS[0]) # default value
w = OptionMenu(master, variable, *OPTIONS)
w.pack()
def ok():
print ("value is:" + variable.get())
button = Button(master, text="OK", command=ok)
button.pack()

Even numbered lines from a text file to a listbox - Python

I have a username-password login system and would like to add a delete user function. The usernames are stored on the even lines of a text file (inc zero) and the passwords on odd numbered lines. Is there a way of adding only the even numbered lines to a listbox to be selected via curselection to be deleted as showing the passwords would be against the point. I currently have all of the contents of the text file showing in the listbox however would like only the usernames to be shown. To delete the lines I have copied the contents of the listbox to a new text file after removing the chosen line from the listbox. Would there also be a way to delete the corresponding password after the username to be deleted has been selected ?
def DelUser():
global rootDU
global listbox
rootDU = Tk()
rootDU.title('Delete user')
users = open(creds, 'r')
mylist = users.readlines()
users.close()
listbox = Listbox(rootDU, width=50, height=6)
listbox.grid(row=0, column=0)
yscroll = Scrollbar(command=listbox.yview, orient=VERTICAL)
yscroll.grid(row=0, column=1, sticky=N + S)
listbox.configure(yscrollcommand=yscroll.set)
enter1 = Label(rootDU, text='Click on the user to delete', width=50)
enter1.grid(row=1, column=0)
for item in mylist:
listbox.insert(END, item)
delButton = Button(rootDU, text='Delete', command=RemoveUser)
delButton.grid(columnspan=2, sticky=W)
delButton.grid(row=2, column=0)
def RemoveUser():
global listbox
try:
index = listbox.curselection()[0]
listbox.delete(index)
os.remove(creds)
newfile = 'tempfile.txt'
with open(newfile, 'w') as f:
f.write(''.join(listbox.get(0, END)))
f.close()
except IndexError:
pass
Just add only every second line to your listbox:
for item in mylist[::2]:
listbox.insert(END, item)
The ::2 slice picks every second line, starting at line 0. See Explain Python's slice notation for further details.
You then still have to re-read the file to find the corresponding password however, since you don't store that information separately. You really want to store a mapping from usernames to passwords (separately, as information you share between DelUser and RemoveUser) so you can easily re-write your user file with the remaining users and passwords.
You could also consider using a different format for your file; writing usernames and passwords on the same line, but putting a delimiter character between them, would make it easier to process the data.

How to read a message using TKInterface?

This is the "click me" function which runs when the button on the interface is clicked.
def click_me():
file_name = file_name_entry.get()
the_file_name = str(file_name)
open(the_file_name, "r")
imp_message = file.read(the_file_name)
There is a grey line beneath the_file_name in brackets and when hovered over says: passing str instead of file - is this intentional?
password_output.delete(0.0, END)
password_output.insert(END, imp_message)
The relevant TKInter code is as follows...
file_name_entry = Entry(encrypt_frame, width=20)
file_name_entry.grid(column = 1, row = 1, sticky = W)
Button(encrypt_frame, text= "Submit", command = click_me).grid(column = 2, row = 1)
The error output is:
IOError: Errno22 invalid mode ('r/) or filename ""
Your code is close, but you're trying to read from the file name rather than the opened file object. Change your code to this:
file=open(the_file_name, "r")
imp_message = file.read()
Better yet, use a context manager which will automatically close the file when you're done:
with open(the_file_name, "r") as f:
imp_message = f.read()
The python documentation has a nice tutorial on reading and writing files:
Python 2 - Reading and writing files
Python 3 - Reading and writing files
Unrelated to the actual question, there are a couple problems with your code.
First, there's no need for this statement:
the_file_name = str(file_name)
In this case, file_name is already a string since it is coming from an Entry widget.
Second, the index 0.0 in the statement password_output.delete(0.0, END) is incorrect. Text widget indexes must be strings in the form of <line>.<column>, and lines start at 1 (one). The proper index for the first character is the string "1.0".

Categories