Files won't be read in GUI program, only in shell [closed] - python

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Hey guys so I have a lengthy code here I need help with,
specifically: my end process is an assignment creating a word cloud, But I haven't even start at that point yet. As of now, I've been able to create the function of creating a frequency accumulator and my first GUI platform.
When running the program, the gui asks the user to type in the file name of their program. However, you can type gibberish or even leave it blank, click the transform file button, and it still opens up Shell and prompts the user for the text file name and then the number of words they want in the list.
I don't even want the 2nd part (asking how many words) but I didn't know another way of doing it for my frequency counter.
from graphics import *
##Deals with Frequency Accumulator##
def byFreq(pair):
return pair[1]
##Function to allow user to upload their own text document##
def FileOpen(userPhrase):
filename = input("Enter File Name (followed by .txt): ")
text = open(filename, 'r').read()
text = text.lower()
for ch in ('!"#$%&()*+,-./:;<=>?#[\\]^_{}~'):
text = text.replace(ch, " ")
words = text.split()
counts = {}
for w in words:
counts[w] = counts.get(w,0) + 1
n = eval(input("Output how many words?"))
items = list(counts.items())
items.sort(key=byFreq, reverse=True)
for i in range(n):
word, count = items[i]
print("{0:<15}{1:>5}".format(word, count))
##This Function allows user to simply press button to see an example##
def Example():
win = GraphWin("Word Cloud", 600, 600)
file = open("econometrics.txt", "r", encoding = "utf-8")
text = file.read()
text = text.lower()
for ch in ('!"#$%&()*+,-./:;<=>?#[\\]^_{}~'):
text = text.replace(ch, " ")
words = text.split()
counts = {}
for w in words:
counts[w] = counts.get(w,0) + 1
n = eval(input("Output how many words?"))
items = list(counts.items())
items.sort(key=byFreq, reverse=True)
for i in range(n):
word, count = items[i]
print("{0:<15}{1:>5}".format(word, count))
#########################################################################
##Gold Boxes##
def boxes(gwin, pt1, pt2, words):
button = Rectangle(pt1, pt2)
button.setFill("gold")
button.draw(gwin)
#Middle of the box coordinates
labelx = (pt1.getX() + pt2.getX())/2.0
labely = (pt1.getY() + pt2.getY())/2.0
#Labels
label = Text(Point(labelx,labely),words)
label.setFill("black")
label.draw(gwin)
####GUI function#####
def main():
#Creates the actual GUI
win = GraphWin("Word Cloud Prompt", 600, 600)
#Box which user types into:
inputBox = Entry(Point(300,150),50)
inputBox.draw(win)
#Gold Boxes at Top
boxes(win, Point(220,300), Point(370,350), "Transform Text File")
boxes(win, Point(220,400), Point(370,450), "Example text file")
#Tells user what to do
prompt = Text(Point(300,25),"Welcome to the Word Cloud program!")
prompt.draw(win)
prompt = Text(Point(300,125),"Enter your textfile name")
prompt.draw(win)
prompt = Text(Point(300,180),"Want to see our own file into a Word Cloud? Click below")
prompt.draw(win)
#display answer
display = Text(Point(300, 500),"")
display.draw(win)
#User Clicks a box:
pt = win.getMouse()
#Store user info
userPhrase = inputBox.getText()
key = inputBox.getText()
#Incase a button isn't clicked
output = "No button was clicked, Please restart program"
#Clicking the Transform Text File Button
if pt.getY() >= 300 and pt.getY() <= 350:
if pt.getX() >= 220 and pt.getX() <= 370:
output = FileOpen(userPhrase)
#Clicking the Example Text File Button
if pt.getY() >= 400 and pt.getY() <= 450:
if pt.getX() >= 220 and pt.getX() <= 370:
output = Example()
#State Answer
display.setText(output)
display.setFill("purple3")
display.setStyle("bold")
prompt.setText("Thank You! Click anywhere to close!")
prompt.setFill("red")
#closing program
pt = win.getMouse()
win.close()
main()

(Editor's Note: I've modified some of the formatting for my ease of reading, but the function will be identical)
def FileOpen(userPhrase):
"""FileOpen allows users to upload their own text document."""
filename = input("Enter File Name (followed by .txt): ")
text = open(filename, 'r').read()
text = text.lower()
for ch in ('!"#$%&()*+,-./:;<=>?#[\\]^_{}~'):
text = text.replace(ch, " ")
words = text.split()
counts = {}
for w in words:
counts[w] = counts.get(w, 0) + 1
n = eval(input("Output how many words?"))
items = list(counts.items())
items.sort(key=byFreq, reverse=True)
for i in range(n):
word, count = items[i]
print("{0:<15}{1:>5}".format(word, count))
This is the function we're concerned with. You call it with an argument userPhrase that comes from a gui text entry field, but then you never use userPhrase anywhere in the function. Consider instead:
def file_open(userPhrase=None):
# file_open is lowercase and snake_case for PEP8
# userPhrase=None to make it an optional argument
filename = userPhrase if userPhrase is not None else \
input("Enter file name (including extension): ")
...
Then you'll have to call it differently if you want file_open to prompt for a filename if not given one.
def main():
...
if 300 <= pt.getY() <= 350 and 220 <= pt.getX() <= 370:
# you can chain conditionals as above. It makes it much easier to read!
# `a <= N <= b` is easily read as `N is between a and b`
userPhrase = inputBox.getText()
if userPhrase.strip(): # if there's something there
file_open(userPhrase)
else:
file_open()

Related

Why does my if statement doesn't repeat when the condition is met?

I'm making a typing speed test and hope when I click space (on_space function) that I could check the user's input with the word list and also delete the typed words in the word list. However, I'm having trouble that the checking and deleting condition is not looping rather than stopping after the 1st word. The issue either be the variable wpm (the word per minute) is not defined when execute at the time the countdown stop or the wpm is always 1, which retains the 1st value typed.
from tkinter import *
import random
import csv
import sys
import time
window = Tk()
# setting tkinter window size
window.state("zoomed")
window.update_idletasks()
window.configure(bg="gray")
window.title("Typing Test")
# opens csv file and converts to list for data management
with open("typingwords.csv", "r") as read_obj: # read csv file as a list of lists
csv_reader = csv.reader(read_obj)
wordList = list(csv_reader)
# Randomizes the list and splices it to only have 150 words
random.shuffle(wordList)
splicedlist = wordList[:150]
# displays the words
fontTuple = ("Playfair Display", 16, "bold")
x1 = Label(window, text=splicedlist, wraplength=1100, fg="white")
x1.config(bg="gray")
x1.config(font=fontTuple)
x1.pack(ipadx=500, ipady=20)
# defines the function used to delete the inside of entry after every space
typedValue = []
def on_space(e1):
global typedValue
global wpm
x = " ".join(splicedlist.pop(0)) # after the word is being typed
if e1.widget.get() != x:
e1.widget.delete(0, "end")
x1.config(text=splicedlist)
pass
else:
typedValue.append(x)
wpm = len(typedValue)
print(wpm)
e1.widget.delete(0, "end")
x1.config(text=splicedlist)
# Timer
sec = int(60)
time = str(f"00:{sec}")
c1 = Label(window, text=time, wraplength=500, fg="white")
c1.config(bg="gray")
c1.config(font=fontTuple)
c1.pack(ipadx=500, ipady=200)
def countdown(count):
if count > 0:
window.after(1000, countdown, count - 1)
c1.config(text=count)
if count == 0:
sys.exit(f"Time's Up! Your words per minute is {wpm}")
fontTuple = ("Playfair Display", 16, "bold")
e1 = Entry(window)
e1.config(font=fontTuple)
e1.bind("<space>", on_space)
e1.bind("<Button-1>", countdown(60))
e1.pack()
window.mainloop()

Brute force password breaker

create a list of word strings by reading this file. Then loop over each word in this list, passing it to the decrypt() method. If this method returns the integer 0, the password was wrong and your program should continue to the next password. If decrypt() returns 1, then your program should break out of the loop and print the hacked password. You should try both the uppercase and lower-case form of each word.
This dictionary.txt file contains words in capital letters.
> import PyPDF2
pdfFile = open('reverse.pdf', 'rb')
pdfReader = PyPDF2.PdfFileReader(pdfFile)
pdfWriter = PyPDF2.PdfFileWriter()
for pageNum in range(pdfReader.numPages):
pdfWriter.addPage(pdfReader.getPage(pageNum))
wrd = input('Please enter one word as a password: ')
pdfWriter.encrypt(wrd)
resultPdf = open('encryptedreverse.pdf', 'wb')
pdfWriter.write(resultPdf)
resultPdf.close()
print(pdfReader.isEncrypted)
helloDict = open('dictionary.txt')
helloDictCont = helloDict.read().splitlines()
liDict = []
for word in helloDictCont:
liDict.extend(word.split())
PdfFile2 = open('encryptedreverse.pdf', 'rb')
pdfReader2 = PyPDF2.PdfFileReader(PdfFile2)
print(pdfReader2.isEncrypted)
for word in liDict:
if pdfReader2.decrypt(word) == 1:
break
print(word)
elif pdfReader2.decrypt(word.lower()) == 1:
break
print(word)
After a few minutes processing ends and I neither get a password printed nor the pdf file is decrypted. Any idea what am I doing wrong?
This works fine for me:
import PyPDF2
pdfFile = open('reverse.pdf', 'rb')
pdfReader = PyPDF2.PdfFileReader(pdfFile)
pdfWriter = PyPDF2.PdfFileWriter()
for pageNum in range(pdfReader.numPages):
pdfWriter.addPage(pdfReader.getPage(pageNum))
wrd = input('Please enter one word as a password: ')
pdfWriter.encrypt(wrd)
resultPdf = open('encryptedreverse.pdf', 'wb')
pdfWriter.write(resultPdf)
resultPdf.close()
print(pdfReader.isEncrypted)
helloDict = open('t.txt')
helloDictCont = helloDict.read().splitlines()
liDict = []
for word in helloDictCont:
liDict.extend(word.split())
PdfFile2 = open('encryptedreverse.pdf', 'rb')
pdfReader2 = PyPDF2.PdfFileReader(PdfFile2)
print(pdfReader2.isEncrypted)
for word in liDict:
if pdfReader2.decrypt(word) == 1:
print('The correct PWD as upper case: ' + word)
break
elif pdfReader2.decrypt(word.lower()) == 1:
print('The correct PWD as lower case: ' + word)
break
else:
print('PWD is not correct: ' + word)
Here's my solution:
'''
Brute-Force PDF Password Breaker
Say you have an encrypted PDF that you have forgotten the password to,
but you remember it was a single English word. Trying to guess your forgot-
ten password is quite a boring task. Instead you can write a program that
will decrypt the PDF by trying every possible English word until it finds one
that works. This is called a brute-force password attack. Download the text file
dictionary.txt from https://nostarch.com/automatestuff2/. This dictionary file
contains over 44,000 English words with one word per line.
Using the file-reading skills you learned in Chapter 9, create a list of
word strings by reading this file. Then loop over each word in this list, pass -
ing it to the decrypt() method. If this method returns the integer 0, the pass-
word was wrong and your program should continue to the next password.
If decrypt() returns 1, then your program should break out of the loop and
print the hacked password. You should try both the uppercase and lower-
case form of each word. (On my laptop, going through all 88,000 uppercase
and lowercase words from the dictionary file takes a couple of minutes. This
is why you shouldn’t use a simple English word for your passwords.)
'''
import PyPDF2
import time
import os
import sys
def decrypt():
ok = False
print(f'Working... {time.asctime()}')
start = time.time()
passwords = open(dictionary).read().split('\n')
pdfReader = PyPDF2.PdfFileReader(pdf)
if pdfReader.isEncrypted:
for password in passwords:
if pdfReader.decrypt(password) or pdfReader.decrypt(password.lower()):
print(f'Password: {password}')
ok = True
break
end = time.time()
hours = int((end - start) / 3600)
minutes = int((end - start) / 60)
secondes = int(end - start - (hours * 3600) - (minutes * 60))
if ok:
print(f'Has been decrypted in {hours}H:{minutes}M:{secondes}S!')
else:
print(f'{pdf} hasn\'t been decrypted... Maybe need a better dictionary?')
else:
print(f'{pdf} isn\'t encrypted')
if len(sys.argv) == 3:
dictionary, pdf = sys.argv[1], sys.argv[2]
if os.path.isfile(dictionary) and dictionary.endswith('.txt'):
if os.path.isfile(pdf) and pdf.endswith('.pdf'):
decrypt()
else:
print('Invalid path to pdf or pdf file')
else:
print('Invalid path to dictionary or dictionary file')
else:
print('Please enter arguments as example:\
\ndictionaryName.txt pdfName.pdf')

How to grab a certain word from a .txt file given what it begins and ends with

DISCLAIMER:
I'm using python 3!
FUNDEMENTAL CODE:
So I have this code:
def login(userlogin):
with open('usernames.txt') as input_data: # Grabs username from usernames.txt CHANGE DOESN'T WORK FOR MULTIPLE PEOPLE
for user in input_data:
if user.strip() == userlogin:
break
for user in input_data:
if user.strip() == '0':
break
print(user)
while(True):
userinput = input('')
login(userinput)
and also .txt file in the same directory, called usernames.txt which you can see here:
admin010
guest020
admin01030
user040
DESIRE:
I want the code to output the username corresponding in the .txt file based on the name inputted, so for example, if you inputted 'admin' it would find text in the text document that starts with admin and find its ending which is always a '0' and output admin010. However, I want it to make sure, when you type admin01 it would output admin01030. So the usernames are in the form, name + value (2 digits i.e. a value of 7 would be 07) + a zero ('0' string).
PROBLEM:
The code isn't working, no matter my input it always outputs the last word in the .txt document. I'm not sure why, any help would be great.
If the format is "name + two-digits + 0", then you want to match the name with a line less the last three characters:
for user in input_data:
if userlogin == user.rstrip()[:-3] # strip trailing whitespace and remove last 3 chars
print(user)
Can be written fairly compactly in this way, if I understand you.
def login(userlogin):
with open('usernames.txt') as usernames:
for line in usernames:
username = line.strip()
if username.startswith(userlogin+'0') and len(username)==len(userlogin)+3:
print (username)
return
print ('no match')
for poss in ['admin', 'admin01', 'guest', 'user']:
print (poss, ': ', end=''); login(poss)
Output:
admin : admin010
admin01 : admin01030
guest : guest020
user : user040
Hi please see below code. But I need to know why admin01 would match admin01030 only? since admin010 also starts with admin01
def login(userlogin):
with open(
'usernames.txt') as input_data: # Grabs username from usernames.txt CHANGE DOESN'T WORK FOR MULTIPLE PEOPLE
for user in input_data:
if user.strip() == '0':
break
if user.strip().startswith(userlogin, 0, len(userlogin)):
break
print(user)
while True:
userinput = input('')
login(userinput)
What you want to do is basically check if a string has a substring.
In the below example when the button is pressed, it checks if the file 'usernames.txt' that is in the same directory, has a string that matches exactly the user input before reaching the last 3 letters which are reserved for value and zero. Then parses it to name, value and '0':
import tkinter as tk
def login():
with open('usernames.txt') as fin:
users_list = fin.readlines()
for user in users_list:
user = user.strip() # to lose \n
if user[:-3] == query.get():
nam_lbl['text'] = user[:-3]
val_lbl['text'] = user[-3:-1]
zero_lbl['text'] = user[-1]
root = tk.Tk()
query = tk.Entry(root)
nam_lbl = tk.Label(root, text="Name: ")
val_lbl = tk.Label(root, text="Value: ")
zero_lbl = tk.Label(root, text="Zero: ")
tk.Button(root, text="Login", command=login).pack()
# layout
query.pack()
nam_lbl.pack()
val_lbl.pack()
zero_lbl.pack()
root.mainloop()

Outputing string data in graphics window

Below is the code I have so far for a simple Caesar cipher program, I am having issues trying to output the encoded data to the graphics window.
The program runs right. But the only output that appears on the screen is the first letter of the coded message, I need the whole coded message to appear on the graphics window.
I think it might be a problem with my loop but can't figure it out. I tried moving the loop around but that just gave two or three repetitions of the first letter.
Any help would be appreciated.
from graphics import*
def main():
win = GraphWin("Caeser Cipher",500,500)
win.setCoords(0.0,0.0,5.0,5.0)
Text(Point(2,4.8),"Caesar Ciper").draw(win)
label1 = Text(Point(1,4),"Please input file:").draw(win)
inputFileName = Entry(Point(2.5,4,),20)
inputFileName.draw(win)
button1 = Text(Point(2.5,3.5),"Open").draw(win)
Rectangle(Point(2.25,3.3),Point(2.75,3.7)).draw(win)
label = Text(Point(1,2.5),"Please input step:")
label.draw(win)
inputstep = Entry(Point(2.5,2.5),20)
inputstep.draw(win)
button2 = Text(Point(2.5,2.0),"Encode").draw(win)
Rectangle(Point(2.25,1.8),Point(2.75,2.2)).draw(win)
button3 = Text(Point(4,1),"Save").draw(win)
Rectangle(Point(3.75,0.8),Point(4.25,1.2)).draw(win)
button4 = Text(Point(4,0.5),"Quit").draw(win)
Rectangle(Point(3.75,0.3),Point(4.25,0.7)).draw(win)
output2 = Text(Point(2.5,1.5),' ')
output2.setTextColor('blue')
output2.draw(win)
while True:
P = win.getMouse()
if(P.getX()>2.25 and P.getX()<2.75 and P.getY()>3.3 and P.getY()<3.7):
fnamein = inputFileName.getText()
infile = open(fnamein, encoding='utf-16', mode='r')
content = infile.read()
output = Text(Point(2.5,3),100)
output.setText(content)
output.setTextColor('red')
output.draw(win)
#infile.close()
if(P.getX()>2.25 and P.getX()<2.7 and P.getY()>1.8 and P.getY()<2.2):
content.strip()
words = content.split()
inputstep1 = inputstep.getText()
#print(inputstep1)
encodedcontent = ' '
for numStr in content:
codeNum = ord(numStr)
#print(codeNum)
encodedcontent = chr(codeNum-eval(inputstep1))
encodedcontent_ascii = ord(numStr)-int(inputstep1)
#print(encodedcontent)
#encodedcontent = encodedcontent + ''
print(encodedcontent)
if(encodedcontent_ascii)<ord('a'):
encodedcontent_ascii = encodedcontent_ascii + 26
#print(encodedcontent_ascii)
'''if str.isalpha(encodedcontent):
encodedcontent = encodedcontent + chr(encodedcontent_ascii)
else:
label.setTextColor('red')'''
encodedcontent = encodedcontent + chr(encodedcontent_ascii)
output2.setText(encodedcontent)
if(P.getX()>3.75 and P.getX()<4.25 and P.getY()>0.8 and P.getY()<1.2):
fnameout = 'encrypt.txt'
data = encodedcontent
outfile = open(fnameout,encoding='utf-16',mode='w')
outfile.write(data)
outfile.close()
if(P.getX()>3.75 and P.getX()<4.25 and P.getY()>0.3 and P.getY()<0.7):
win.close()
main()
I think the problem lies in this loop:
encodedcontent = ' ' # initialise
for numStr in content:
...
encodedcontent = chr(codeNum-eval(inputstep1)) # overwrite
...
encodedcontent = encodedcontent + chr(encodedcontent_ascii) # add
encodedcontent will only be two characters at most, when presumably you want to build up the whole string.
More generally, putting all of your code into one place makes this difficult to debug. I suggest breaking it into smaller functions; at the very least, separate the encryption of a string out from the user interface.

Python- Saving Results to a File and Recalling Them

I'm writing a program in Python that will store Student IDs, names, and D.O.B.s.
The program gives the user the ability to remove, add, or find a student. Here is the code:
students={}
def add_student():
#Lastname, Firstname
name=raw_input("Enter Student's Name")
#ID Number
idnum=raw_input("Enter Student's ID Number")
#D.O.B.
bday=raw_input("Enter Student's Date of Birth")
students[idnum]={'name':name, 'bday':bday}
def delete_student():
idnum=raw_input("delete which student:")
del students[idnum]
def find_student():
print "Find"
menu = {}
menu['1']="Add Student."
menu['2']="Delete Student."
menu['3']="Find Student"
menu['4']="Exit"
while True:
options=menu.keys()
options.sort()
for entry in options:
print entry, menu[entry]
selection=raw_input("Please Select:")
if selection =='1':
add_student()
elif selection == '2':
delete_student()
elif selection == '3':
find_students
elif selection == '4':
break
else:
print "Unknown Option Selected!"
The problem I am having is I cannot figure out how to have the program save any added records to a file when the program ends. It also would need to read back the records when the program restarts.
I keep trying to find tutorials for this sort of thing online, but to no avail. Is this the sort of code I'd want to add?:
f = open("myfile.txt", "a")
I'm new to Python so any help would be appreciated. Thanks so much.
It depends, if you want to actually save python objects, check out Pickle or Shelve, but if you just want to output to a text file, then do the following:
with open('nameOfYourSaveFile', 'w') as saveFile:
#.write() does not automatically add a newline, like print does
saveFile.write(myString + "\n")
Here's an answer that explains the different arguments to open, as in w, w+, a, etc.
As an example, say we have:
with open('nameOfYourSaveFile', 'w') as saveFile:
for i in xrange(10):
saveFile.write(name[i] + str(phoneNumber[i]) + email[i] + "\n")
To read the file back, we do:
names = []
numbers = []
emails = []
with open('nameOfYourSaveFile', 'r') as inFile:
for line in inFile:
#get rid of EOL
line = line.rstrip()
#random example
names.append(line[0])
numbers.append(line[1])
emails.append(line[2])
#Or another approach if we want to simply print each token on a newline
for word in line:
print word
import pickle,os
if os.path.exists("database.dat"):
students = pickle.load(open("database.dat"))
else:
students = {}
... #your program
def save():
pickle.dump(students,open("database.dat","w"))

Categories