Reputation: 3
I'm looking to make a library type program that allows you to take out a book from a small "database" text file, and then amend the line in the file to include the user ID previously entered to show that it's taken.
The user ID when entered has to be an integer and 4 digits long, which I've got the program to work out with a try/except, except now when it comes to moving on to actually write the file, it no longer seems to run past asking for the book_id although it was functional before I put in everything checking for the right length of ID.
Also this is all meant to be inside a "def checkout()" function (so i can later right a main program including the search function I wrote and one that allows you to 'return' the books) but if I try to put it inside it all I get are indent errors, and whenever I tried to use breaks in order to stop the program from repeating "Sorry, either the book ID was not found or the book is unavailable" for every book or every other book the whole thing would die. At this point I'm just looking for basic functionality even if it doesn't work perfectly so the main priority is to get it actually running.
while True:
txt = open("book_list.txt", "r+")
try:
user_id = int((raw_input("Please enter your ID: ")))
if len(str(user_id)) != 4:
print "Sorry, that was an invalid ID. Please try again."
continue
break
except:
print "Sorry, that was an invalid ID. Please try again."
book_id = (raw_input("Please enter the book ID no. you would like to take out: "))
for line in txt:
if book_id == line[0] and line[-1] == " ":
txt.write(line.replace(line,user_id))
print "You have successfully taken out the book."
else:
print "Sorry, either the book ID was not found or the book is unavailable."
txt.close()
The text file in question is just:
1 Book_1 Author_1 1234
2 Book_1 Author_1
3 Book_2 Author_2
4 Book_3 Author_3 2000
5 Book_4 Author_3
The book ID is the number on the left and the user ID (or space " " which means that the book is available) is the right hand number.
It's probably something really simple that I'm missing and have done to make it not work because I'm a beginner but I appreciate any input, cheers.
Upvotes: 0
Views: 62
Reputation: 69
First off, you can easily verify the id without using exceptions:
def id_valid(id):
return len(id) == 4 and id.isdigit()
The isdigit() method returns true if all characters in a string are digits.
Reading the correct id could then be done like this:
PROMPT = "Please enter your ID: "
user_id = raw_input(PROMPT)
while not id_valid(user_id):
print "Sorry, that was an invalid ID. Please try again."
user_id = raw_input(PROMPT)
The "Sorry, either the book ID was not found or the book is unavailable." message gets shown so many times because you print it in every iteration where the id doesn't match or the book is unavailable. You can use a boolean flag to remember whether the book was found and print that message once, at the end:
book_found = False
with open("book_list.txt", "r") as txt:
for line in txt:
data = line.split();
if book_id == data[0] and len(data) == 3:
# modify the file here
print "You have successfully taken out the book."
book_found = True
if not book_found:
print "Sorry, either the book ID was not found or the book is unavailable."
Given that your data entries in each line are separated by whitespace, you can use split to separate the id's. It will return a list where the [0] element is the book id and [3] is the user id (if it exists). If there is no user id, the list is going to only have 3 elements.
As for updating the file, the simplest strategy is saving a modified copy as you process the original file and overwriting it if you want to save your modifications at the end.
Upvotes: 1
Reputation: 1857
First of all remove open statement from while
loop , it keeps opening file unnecessarily.
while True:
try:
user_id = int((raw_input("Please enter your ID: ")))
if len(str(user_id)) != 4:
print "Sorry, that was an invalid ID. Please try again."
continue
break
except:
print "Sorry, that was an invalid ID. Please try again."
book_id = (raw_input("Please enter the book ID no. you would like to take out: "))
Secondly use with
statement while
dealing with files so you dont have to keep track of closing it.
Also opening your file in "r+"
mode is going to complicate the issue as data is going to be appended in the end, you may utilize seek
and tell
but it is not going to make things any easier also you may overwrite your data, so i suggest you to use a temporary file
out_txt = open("temp.txt","w")
found = False
with open("book_list.txt", "r") as txt:
for line in txt:
if book_id == line[0] and line[-1] == " ": # are you sure that every line that does not have an user_id associated to it is going to have a " "(space) at the end of it, if not think of some other condition to do this
line = line.strip() + " " + str(user_id) + "\n"
print "You have successfully taken out the book."
found = True
out_txt.write(line)
out_txt.close()
if found:
import os
os.remove("book_list.txt")
os.rename(out_txt.name, "book_list.txt")
else:
print "Sorry, either the book ID was not found or the book is unavailable."
Upvotes: 0
Reputation: 987
There are a couple of problems in your code:
Dont open the file in the while loop but before (and propably add error checking)
while True:
txt = open("book_list.txt", "r+")
If you write to a r+
file you will append all lines written by txt.write
to the end of the file.
Not overwrite them! This means that after checking a book out you will have a new line
in the end of the file that the book is checked out. Overwriting in a file is more complex!
There are basically two solutions either you read in the whole file and safe it in a dictionary or sth. and then rewrite the full file with w
.
Or and this is a bit ugly you put exactly four spaces after each book and overwrite these with the number of the user by using txt.seek
.
The comparison book_id == line[0]
basically means that you check wether the first character of line
is equal to the number of the book, which is not the same as checking if the first number of the line is the same as your book id
book_id == int(line[0:line.index(" ")])
The Indent errors you get are hard to check but basically you have to check you're IDE or texteditor if it handles the spaces and tabs correctly or if you somehow did not care about the indents enought.
Upvotes: 0