Python - read and write input from user - python

I am having trouble writing this short program for my python class I was hoping someone could offer some assistance.
What I would like to accomplish:
1. Write a program that uses a while loop to accept input from the user (if the user presses Enter, exit the program).
2. Save the input to a file, then print it.
3. Upon starting, the program will display the current contents of the file.
Example:
Start program for first time.
Enter text: this is input
this is input.
Enter text: some more text
this is input. some more text.
When you start the program for a second time
this is input. some more text.
Enter text:
etc. etc.
What I have so far:
intext = open('user_input.txt','a')
intext.close()
string_input = input('Enter text: ')
while True:
open_input = open('user_input.txt','r')
if open_input:
for i in open_input:
print(i)
if string_input != "":
uinput = open('user_input.txt','a')
uinput.write(string_input + '.')
uinput.close()
rd = open('user_input.txt', 'r')
if rd:
for line in rd:
print(line)
if string_input == "":
t = open('user_input.txt', 'r')
for line in t:
print(line)
t.close()
break
Problems: Upon opening, any previously stored text does not display. If a user inputs text it prints in an infinite loop, and does not prompt to enter text again.
Positives: The input is recorded to the text file. If no text is entered, when exiting any previously entered text does display correctly.
Like I said, this is homework for me. I have searched for the answer, but I seem to be ripping the code apart and putting it back together only to get different errors. So some guidance on this would be greatly appreciated.
One thing I forgot to mention is that I am using Python 3.
Thanks again to David for helping me think more like a programmer. Here are the results:
intext = open('user_input.txt','r').readline()
print(intext)
while True:
string_input = input('Enter text: ')
if string_input == "":
t = open('user_input.txt', 'r').readline()
print(t)
break
if string_input != "":
d = open('user_input.txt', 'a')
d.write(string_input + '. ')
d.close()
n = open('user_input.txt', 'r').readline()
print(n)
I tried to keep the code as slim as possible, and it works now.
A couple questions additional questions that came out of this:
Do I need to close the file at the end? When I tried to close apnd and n , It gave me errors.
While looking for answers I came a across, this. Is it still best practice to use a "with" statement?
Example:
with open("x.txt") as f:
data = f.read()
do something with data

To be honest, your program as you've shown it is kind of a mess. I say this not to be insulting, but because you do have a pretty clear list of the steps your program needs to take, and I think you will wind up with a better understanding by scrapping your existing code and starting from scratch.
In your question, you listed the following steps:
Upon starting, display any previous content of the file
Use a while loop to
Accept input from the user
If the user presses Enter, exit the program
Save the input to a file
Print it (note: did you mean to print just the latest input, or everything in the file?)
Turning your overall task into a list of specific steps like this is probably 80% of the work of writing a computer program. All that's left to do is translate it into code. So I would suggest that you consider how to do each of these steps individually.
Write a code snippet to display the contents of a file
Write a code snippet to read a line of input from the user and store it in a variable
Write a code snippet to check the contents of a variable to see whether it's empty, and if so, exit
Write a code snippet to append the contents of a variable to a file
Write a code snippet to print the contents of a variable (or of a file, if that's what you meant to do)
Each of these can be done in one or two lines, so individually, you should have an easy time with them. Once you've done all the pieces, all you need to do is put them together:
# display the contents of the file
while True:
# read a line of input and store it in a variable
# check the contents of the variable to see if it's empty, and if so, exit
# append the contents of the variable to the file
# print the contents of the variable (or of the file)
Update: This is not a big deal, but you have an unnecessary if statement (the second one) in your revised program. Think about this: if string_input is empty, Python will execute the break statement, which terminates the loop immediately. So you'll only ever reach the second if statement if string_input is not empty. That means the condition string_input != "" is guaranteed to be true at that point in the program, and there's no need to check it.
Do I need to close the file at the end? When I tried to close apnd and n , It gave me errors.
Yes you do. Look at the pattern you used with d:
# open the file
d = open('user_input.txt', 'a')
# write to it (or read from it)
d.write(string_input + '. ')
# close it
d.close()
You should do the same thing every time you open a file, namely with intext, t, and n: open it, read from it, and then immediately close it.*
I'm guessing that the reason you encountered errors is that you tried to put the .close() statements at the end of the program, outside of the if statement and perhaps even outside of the while loop. That would give you a NameError because the variables n and t are not defined at those points in the program. They "expire" at the end of the block they are defined in. For more information on this, read up on scoping. (The Wikipedia article is probably not the best introduction, but you can search Stack Overflow and/or the web for more resources.)
While looking for answers I came a across, this. Is it still best practice to use a "with" statement?
Yes, the with statement is relatively new to Python and is the recommended way to do "quick" file I/O operations like this. Basically the with block takes care of closing the file at the end. For example, the code snippet above involving d is equivalent to
# open the file
with open('user_input.txt', 'a') as d:
# write to it (or read from it)
d.write(string_input + '. ')
# Python "automatically" closes it for you
*This "open-read/write-close" pattern of file access is usually a good idea. I've told you to use it in your program because it's important for you to learn how to split a program into small steps and convert each of the steps into code individually. But when you are writing a program that repeatedly writes things out to a file, or reads them in from a file, sometimes it is actually better to just open the file once in the beginning and just keep it open, rather than opening and closing it every time. If you are curious, one thing you could investigate is how to modify your program to reduce the number of times it has to open and close the file.

Use raw_input instead of input.
You forget to call input in the while loop
BTW, why not write data just at exit of the program instead of in each loop?

Related

Python notebook: Reading the note from a file

I am having trouble with one of my online coding exercises that I am trying to complete. The program does not read my note from the program as it should.
The exercise is simple, it wants me to add a code and then read it with time format and has other some menu options:
The last exercise in this chapter adds a small feature to the other continuous exercise project, the notebook. In this exercise, add a feature which includes the date and time of the written note to the program. The program works as earlier, but saves data in the form [note]:::[date and time] meaning that there is a three-colon separator between the note and timestamp. The timestamp can be generated as follows:
import time
time.strftime("%X %x")
'19:01:34 01/03/09'
This returns the date and time in a nice, compact string. When
working correctly, the program prints the following:
(1) Read the notebook.
(2) Add note.
(3) Empty the notebook.
(4) Quit
Please select one: 2.
Write a new note: Play football.
(1) Read the notebook.
(2) Add note.
(3) Empty the notebook.
(4) Quit.
Please select one: 1.
Play football:::21:11:24 11/04/11.
(1) Read the notebook.
(2) Add note.
(3) Empty the notebook.
(4) Quit.
Please select one: 4.
Notebook shutting down, thank you.
import time
try:
f=open("notebook.txt","r")
except Exception:
mf=open("notebook.txt","w")
mf="notebook.txt"
promptForNumbers = True
while True:
if promptForNumbers:
print("(1) Read the notebook\n(2) Add note\n(3) Empty the notebook\n(4) Quit\n")
selection=int(input("Please select one: "))
if selection==1:
handle = open(mf,"r")
filetext = handle.read()
print(filetext)
elif selection==2:
filetext=input("Write a new note: ")
myfile= open(mf, "w")
myfile.write(filetext)
myfile.write(":::")
myfile.write(time.strftime("%X %x"))
elif selection==3:
readfile = open(mf,"w")
readfile.close()
print("Notes deleted.")
elif selection == 4:
print("Notebook shutting down, thank you.")
break
else:
print("Incorrect selection")
You are missing myfile.close() after you finish writing to the file.
Ideally you should be closing the file after you finish operating on it (so it would be good to close handle.
Also, this might be bad formatting, but if your larger if is outside of while then you have to remove break in selection==4.
It looks like you are opening the file multiple times and not closing it, which could cause problems. Use with to handle files instead, as this will close the file automatically at the end of the block. Use try...except block to test whether the file exists at the point where the user tries to access it, rather than doing this at the start of the program.
import time
# Remove these lines which open the file without closing it (were you testing whether the file exists?)
#try:
# f=open("notebook.txt","r")
#
#except Exception:
# mf=open("notebook.txt","w")
mf="notebook.txt"
promptForNumbers = True
while True:
if promptForNumbers:
print("(1) Read the notebook\n(2) Add note\n(3) Empty the notebook\n(4) Quit\n")
selection=int(input("Please select one: "))
if selection==1:
try:
with open(mf) as f:
print(filetext.read())
except FileNotFoundError:
print("The notebook file was not found")
elif selection==2:
text = input("Write a new note: ")
with open(mf, "w") as f:
f.write(text)
f.write(":::")
f.write(time.strftime("%X %x"))
elif selection==3:
with open(mf, "w") as f:
pass
print("Notes deleted.")
elif selection == 4:
print("Notebook shutting down, thank you.")
break
else:
print("Incorrect selection")
The main problem is that you are not handling files the right way. They should not be opened at the start of the program and they have to be closed each time after use. Also, you need the "a" mode for appending. For starters, remove the try and except blocks, since they only cause problems and mf is overridden anyway.,
The next problem is the string argument that encodes the mode. If you want to read the file, you have to use "r", if you want to write something, you need "a" (or "r"). So if you want to be able to do both, you have to open the file each time the user chose an option. Finally, you have to close the file when you don't need it at the moment and that can be easily done by the with open([filename], [mode]) as file: term that automatically handles opening, closing and Errors in a save and readable way.
So for example:
if selection==1:
handle = open(mf,"r")
filetext = handle.read()
print(filetext)
should become:
if selection==1:
with open(mf, "r") as file:
filetext = file.read()
print(filetext)
That should solve every problem that is caused by interaction with files. though the rest of the code is rough on the eyes too and could use some refactoring (and should not be included in a StackOverflow question. Please try to provide minimal examples of your problem or question). Using f-Srings might be a nice way to get the task done in an easy and readably way.
change selection 1 to the following code. It Should work.
if selection==1:
with open(mf, "r") as f:
print(f.read())
From the first glance, your file handling is wrong.
try:
f=open("notebook.txt","r")
except Exception:
mf=open("notebook.txt","w")
This thing really confuses me about why it is there, as you never use f anywhere, do not close it and if it raises an error you are opening the file as mf but you immediately lose the reference to it as you assign a filename to mf.
You are opening the file multiple times, but rarely close it.
The preferred way of opening a file in Python is using context manager like so:
with open(mf, "w") as myfile:
myfile.write(filetext)
myfile.write(":::")
myfile.write(time.strftime("%X %x"))
This way when you exit the with block you are guaranteed to have your file closed.

I do not know how to set the list to move to the next element when run the program the second time

def get_room(self):
if self.var2.get() == 'Deluxe Room':
self.not_served_deluxe = [x for x in range(101,200)]
self.served_deluxe = []
self.take_room = self.not_served_deluxe[0]
self.not_served_deluxe.remove(self.take_room)
self.served_deluxe.append(self.take_room)
self.room_win = tk.Tk()
self.room_win.geometry('400x600')
self.room_lb = tk.Label(self.room_win,text='Room No.',font=('Helvetica',20))
self.room_lb.grid(row=0,column=0,padx=20,pady=10)
For this program, I would like to set the first element of list self.not_served_deluxe into 101 then if run the program second time move to 102 for the first element. However I do not know what method should I use in order to let the second element to be the first one when run the program next time. If possible can anyone help to solve?
If you want to store something between runs of the script you should write it to a file. There are many options like pickle, csv, or just opening a file and writing to it.
with open("./myfile.txt", "w") as file:
file.write(101)
Next run
with open("./myfile.txt", "r") as file:
room = (file.read())
# ... Do stuff here
with open("./myfile.txt", "w") as file:
file.write(room + 1)
first explanation:
you could create a new variable, which you call a counter and then count up every time it has gone through and then just make an if statement
pseudocode:
if variable =1-> execution1
else -> execution two
second explanation:
so if i understand you correctly you want to do a different execution of the program when the program is run through 1 time. is that correct? If yes, then create a variable that counts how often you go through the code and then create an if statement from this variable, which contains the necessary statement. Do you understand what I mean? Or in which place should I explain it in more detail

Program copies specific lines from HTML file; certain lines break it with no visible pattern?

I have written a program in Python to take the text from specific elements in an HTML file ('input') and write it all into another document ('output'). The program works by searching for the particular HTML tag that precedes all elements of the desired type, and then writing the next line. This is the code, generalized:
input = open(filepath, 'r')
output = open(filepath2, 'w')
collect = 0
onstring = "string to be searched for"
for i in range(numberOfLines):
line = input.readline()
if onstring in line:
collect = 1
elif collect == 1:
output.write(line)
collect = 0
I doubt it is optimal, but it functions as intended except for one hangup: For every HTML file I try this on, between 5 and 15 of the last elements that should be copied get completely cut off. There is seemingly no pattern to what amount are cut off, so I was wondering if someone more experienced with Python could point out an apparent flaw.
If it helps, some things I have tested:
if I append two HTML files, the same amount of posts will be cut off as are cut off from the second one alone.
if I remove the last element that gets copied, more elements that were cut off after it are copied as normal, but usually some posts get cut off later, suggesting that the particular element that is copied is responsible for this issue. There is no discernible pattern of which ones 'break' the program, though.
Expanding on my comment from above. You have opened the file for writing, but each write operation does not go directly to disk. Instead, it is sent to a write buffer; when the buffer fills up, all of the write operation in the buffer are written to the physical disk. Closing the file forces whatever write operations are in the buffer to be written out.
Since your program exits without closing the file, you have writes left in the memory buffer that were never written to disk. Try using:
output.close()
I solved the problem by properly closing the files with output.close().
Credit goes to James for his helpful comment.
If not, you may have writes left in the memory buffer that were never
written to disk. Try using output.close().

How to append a list so that the changes are persistent?

I am new to Python and relatively new to coding in general, I was just trying to write a test bit of code to see if a list could be appended, and then when that .py is reloaded the changes are saved into it?
I'm not sure if this is possible with lists without a decent amount more work, but none of my attempts have managed to get me there.
The test code I have at the moment is:
lDUn = []
lDPw = []
def enterUn():
usrName = input(str("Enter your desired username:\n"))
if usrName in lDUn:
print ("Username is already in use, please try again")
enterUn()
else:
print ("Username created!")
lDUn.append(usrName)
enterUn()
def enterPw():
pW1 = input(str("Enter your desired password:\n"))
pW2 = input(str("please re-enter your password:\n"))
if pW1 == pW2:
print ("Password created!")
lDPw.append(pW1)
else:
print ("Passwords do not match, please try again")
enterPw()
enterPw()
When lDUn and lDPw are checked for inclusion later on they register no problem, but when the program is closed and re-opened later they are gone.
I have tried making it writing the 'pW' and 'usrName' inputs into a .txt but have failed to get it to search those .txts for the specific strings later on. (but that is for a different question) Other than that I'm not sure what to do with my current knowledge of Python.
The values of variables (in this case, the contents of your lists) are never automatically saved when you restart the program. You would need to write some code that saves the values to a file before the program exits, and also some code that reads the values in from the file when the program starts up again.
It's up to you just how you convert the lists into bytes that you can put in a file. One common way would be to just write the strings from the lists into the file, one per line, and then read them again. You can do this using the methods of file objects.
Another option is to use the pickle module. This may save you a bit of effort, since you just give it a Python object and it handles the conversion into bytes for you, but you won't be able to view and edit the resulting file. (Well, you can, but it will look like gibberish since it's a binary file.)
Here's basically what you do:
You set a file or files where you will store those lists.
At the begining of your code you load the data from files into lists.
Each time you modify one of the lists you also modify the related file (the most basic implementation would be to recreate the file).
You work with in-memory data in other cases.
That will work fine as long as you deal with small files and small "traffic". If any of those increases then you will have serious peformance and/or consistency issues. To properly solve these problems you should use a proper database, starting with sqlite (which doesn't require a separate server).

How can I have my program read updates that it has just made to a text file?

I am brand new to Python (just started it 5 hours ago) but I have about a year of experience with Java. Anyways, the first program I wanted to make would create a sort of 'log book' of names/Birthdays. It prompts the User for the number of entries, then the names and birthdates. It is fairly simple and works fine. Each time you run the Program it appends the new Names/Birthdates, to the text file so The previous names/birthdates remain intact and the new ones appear at the end. However I wanted to be able to sort these entries by last name. I successfully create a way to sort them by last name (again its not to complex) however It only works if It is its own separate program. If i place the code at the end of my original program, It will sort as expected, however it will not sort any of the new entries made in the program, only the entries from the last time the program was run. I did close the file and re-open it in the code after the entries were made, however it still will not recognizes the changes made. Because Both programs function properly on their own, what do I need to do in order to implement these two pieces of code in the same program? Alternatively, would there be a way to run the second program from the first program?
Here is my programs code (BirthDates.txt is the text file were the entries are stored):
#IDLE 1.2.4
#Begin Entries
fileobja=open("BirthDates.txt","a")
dates=int(raw_input("Number of entries to add:"))
count=0
while count<dates:
fileobja.write("*NEW ENTRY*")
firstName=raw_input("Enter user's first name:")
lastName=raw_input("Enter user's last name:")
DOB=raw_input("Enter user's date of birth (MM/DD/YYYY):")
print lastName+","+firstName+"\n"+DOB
fileobja.write("\n")
fileobja.write(lastName+", "+firstName+"\n")
fileobja.write("("+DOB+")"+"\n"+"__________\n")
#print "dates=",dates
#print "count=",count
count=count+1
#print "count=",count
fileobja.close
#End Entries
This is the second Program:
#Begin Sorter
fileobjr=open("Birthdates.txt","r")
fileList=[]
tempString=""
tempStringCount=0
for line in fileobjr:
tempString="".join(line[0:])
#print "tempString="+tempString
fileList.append(tempString)
tempStringCount=tempStringCount+1
fileobjr.close
fileListLength=len(fileList)
#print fileListLength
chunks=(fileListLength)/4
sortCount=1
tempList=[]
while sortCount<fileListLength:
templine=fileList[sortCount]+fileList[sortCount+1]
tempList.append(templine)
sortCount=sortCount+4
writeCount=0
tempList.sort()
fileobjw=open("BirthDates.txt","w")
while writeCount<chunks:
#print tempList[writeCount]
fileobjw.write("*NEW ENTRY*\n")
fileobjw.write(tempList[writeCount])
fileobjw.write("__________")
fileobjw.write("\n")
writeCount=writeCount+1
fileobjw.close
#End Sorter
The problem is here:
fileobja.close
… and a few similar lines.
You're not calling the close method, you're just referencing it as a value. So, the file doesn't get closed, which means it doesn't get flushed, which means anything you've written to it may not be available to read yet.
To fix it, just call the method:
fileobja.close()
As a side note, it's usually easier to use a with statement, which takes care of closing the file when you exit the block inside it. (It's like a magic try/finally.) Instead of this:
f = open('foo', 'a')
do_stuff(f)
do_more_stuff(f)
# ...
f.close()
Do this:
with open('foo', 'a') as f:
do_stuff(f)
do_more_stuff(f)
# ...

Categories