I'm trying to write a program for checking out/returning books at the library and I'm using temporary lists as storage for all the data in the patrons.txt and books.txt so I can edit it and then put it back in. The problem is that when I try to print the tempBookFile and tempPatronFile to outfile, the "file = outfile" part of following line
print(tempBookFile, file = outfile)
is highlighted in yellow and when I hover over it it says Expected type 'Optional[IO[str]] got 'TextIOWrapper[str]' instead". As a result, everything in the book list and patron list gets deleted, except for the name of the book which is stored in the patron file while it is checked out.
class Book:
def __init__(self, title, author, genre, isbn):
self.title = title
self.author = author
self.genre = genre
self.isbn = isbn
def printAll(self,outfile):
print(self.title, "|", self.author, "|", self.genre, "|", self.isbn, file = outfile)
class Patron:
def __init__(self, name, phone, books):
self.name = name
self.phone = phone
self.books = books
def printAll(self, outfile):
print(self.name, "|", self.phone, "|", self.books, file = outfile)
def main():
print("Welcome to JCK library!")
menu = eval(input("Main menu. Type 1 to enter books, 2 for new patron, 3 to check out book, 4 return book, 5 show status, 6 exit. "))
while(menu != 6):
if(menu == 1):
outfile = open("books.txt", "w")
title = input("Enter title: ")
while(title != "done" and title != "Done"):
author = input("Enter author: ")
genre = input("Enter genre: ")
isbn = input("Enter isbn: ")
book = Book(title,author,genre,isbn)
book.printAll(outfile)
print("Book added: ", title)
print("Author: ", author)
print("Isbn: ", isbn, "\n")
title = input("Enter title: ")
outfile.close()
menu = eval(input( "Main menu. Type 1 to enter books, 2 for new patron, 3 to check out book, 4 return book, 5 show status, 6 exit. "))
elif(menu == 2):
outfile = open("patrons.txt", "w")
name = input("Enter patron name: ")
phone = input("Enter phone number: ")
books = []
patron = Patron(name,phone,books)
patron.printAll(outfile)
outfile.close()
menu = eval(input("Main menu. Type 1 to enter books, 2 for new patron, 3 to check out book, 4 return book, 5 show status, 6 exit. "))
elif(menu == 3):
title = ""
author = ""
genre = ""
isbn = ""
name = ""
phone = ""
books = []
outfile = open("patrons.txt", "r")
patronName = input("Enter Patron Name: ")
if (patronName in outfile.read()):
print("Patron found.")
for line in outfile.readlines():
if(patronName in line):
patronInfo = line.split("|")
name = patronInfo[0]
phone = patronInfo[1]
books = patronInfo[2]
#Creates a temporary list containing all of the contents of the patrons.txt file so that
#the list can be modified and then put back into the patrons.txt file
tempPatronFile = outfile.readlines()
#Removes the line from the temporary list that contains information about the patron who is checking out
#a book so that it can be re-added to the list after it is updated
for line in tempPatronFile:
if(patronName in line):
tempPatronFile.pop(line)
outfile.close()
outfile = open("books.txt", "r")
bookName = input("Enter Book Name: ")
if bookName in outfile.read():
books.append(bookName)
for line in outfile.readlines():
if(bookName in line):
bookInfo = line.split("|")
title = bookInfo[0]
author = bookInfo[1]
genre = bookInfo[2]
isbn = bookInfo[3]
book = Book(title,author,genre,isbn)
#Creates a temporary list containing all of the contents of the books.txt file so that
#the list can be modified and then put back into the books.txt file
tempBookFile = outfile.readlines()
#Removes the line from the temporary list that contains information about the book so that
#the book can be re-added later after it has been returned.
for line in tempBookFile:
if(bookName in line):
tempBookFile.pop(line)
outfile.close()
outfile = open("books.txt", "w")
print(tempBookFile, file = outfile)
outfile.close()
outfile = open("patrons.txt", "w")
print(tempPatronFile, file = outfile)
patron = Patron(name,phone,books)
patron.printAll(outfile)
book.printAll(outfile)
outfile.close()
print("Book due in 2 weeks.")
menu = eval(input("Main menu. Type 1 to enter books, 2 for new patron, 3 to check out book, 4 return book, 5 show status, 6 exit. "))
elif(menu == 4):
outfile = open("patrons.txt", "r")
patronName = input("Enter patron name: ")
if(patronName in outfile.read()):
for line in outfile.readlines():
if(patronName in line):
patronInfo = line.split("|")
name = patronInfo[0]
phone = patronInfo[1]
books = patronInfo[2]
bookName = input("Enter book name: ")
if(bookName in outfile.read()):
for line in outfile.readlines():
if(bookName in line):
bookInfo = line.split("|")
title = bookInfo[0]
author = bookInfo[1]
genre = bookInfo[2]
isbn = bookInfo[3]
book = Book(title, author, genre, isbn)
# Creates a temporary list containing all of the contents of the patrons.txt file so that
# the list can be modified and then put back into the patrons.txt file
tempPatronFile = outfile.readlines()
# Removes the line from the temporary list that contains information about the patron who is checking out
# a book so that it can be re-added to the list after it is updated
for line in tempPatronFile:
if (patronName in line):
tempPatronFile.pop(line)
#Removes the information about the book which was stored in the patron file while it was checked out.
#Upon being returned, the book will go back into the books.txt file
for line in tempPatronFile:
if(bookName in line):
tempPatronFile.pop(line)
outfile.close()
outfile = open("books.txt", "r")
tempBookFile = outfile.readlines()
tempBookFile.append(book)###################################
outfile.close()
outfile = open("books.txt", "w")
print(tempBookFile, file = outfile)
outfile.close()
outfile = open("patrons.txt", "w")
for line in books:
if(bookName in line):
books.pop(line)
patron = Patron(name,phone,books)
print(tempPatronFile, file = outfile)
patron.printAll(outfile)
outfile.close()
print("Book returned.")
menu = eval(input("Main menu. Type 1 to enter books, 2 for new patron, 3 to check out book, 4 return book, 5 show status, 6 exit. "))
elif(menu == 5):
outfile = open("patrons.txt", "r")
patronName = input("Input patron's name: ")
if(patronName in outfile.read()):
for line in outfile.readlines():
if(patronName in line):
patronInfo = line.split("|")
name = patronInfo[0]
phone = patronInfo[1]
books = patronInfo[2]
print(patronName, "has the following book(s) checked out:\n", books)
menu = eval(input("Main menu. Type 1 to enter books, 2 for new patron, 3 to check out book, 4 return book, 5 show status, 6 exit. "))
print("Have a nice day!")
main()
The issue has to do with your old school file opening. You should avoid using open and close to manage your files and instead use a with statement. Most of the time if you are using resources that need to be cleaned up/managed you should use
with open("my_file.txt", "w") as output_file:
# File based operations here
And then PyCharm will be happy. You can see a similar problem here: PyCharm - Expected type 'Optional[IO[str]]', got 'TextIOWrapper[str]' instead
Also as someone commented (it's now deleted) make sure you are opening the file in the correct mode. "w" will erase everything in the file and let you write to it. "r" will only let you read from it. "a" will let you append to the file and might be what you want. If you look up the inputs to open you can get the full details. https://docs.python.org/3/library/functions.html#open
Related
Trying to do a contact list where you can add and remove people from a .txt, i can add people but i get this line of error when i try to write out all the lines in the txt but the one i want to remove. I've seen other threads but don't understand what i should change.
Error: AttributeError: 'list' object has no attribute 'write'
from model_contact import Contact
toDo = input("Add or remove contact: ")
if toDo == "add":
name = input("Name: ")
contactlist = open("contactlist.txt", "a")
contactlist.write("\n" + name)
contactlist.close()
print(name + " is now added to the contactlist!")
elif toDo == "remove":
name = input("Name of removal: ")
contactlist = open("contactlist.txt", "r")
lines = contactlist.readlines()
contactlist.close()
open("contactlist.txt", "w")
for line in lines:
if line.strip("\n") != name:
lines.write(line)
Just to sum up all the comments from above in a code snippet :
from model_contact import Contact
toDo = input("Add or remove contact: ")
name = input("Name: ")
if toDo == "add":
with open("contactlist.txt", "a") as contactlist:
contactlist.write("\n" + name)
print(name + " is now added to the contactlist!")
elif toDo == "remove":
with open("contactlist.txt", "r") as contactlist:
lines = contactlist.readlines()
with open("contactlist.txt", "w") as ncl: #cnl == new contact list
for line in lines: # lines here are the read lines from above
if line.strip("\n") != name:
ncl.write(line)
This code is very direct and has a serious flaw, which is the the second opening of the file, which if it is a big one, could be a problem.
To reduce the impact if the file is big, i would try this:
with open("contactlist.txt", "r+") as contactlist:
lines = contactlist.readlines()
tmp = []
for num, line in enumerate(lines):
if line.strip("\n") == name:
tmp.append(num)
for num in tmp:
lines.pop(num)
contactlist.writelines(lines)
I'm facing a problem where I can't finish my code.
There is a problem where upon running this code it comes up as an IndexError.
name = str(input("Please input the books name that you would like to borrow: ")
file = open("books.txt", "r")
file_contents = []
for line in file:
stripped_line = line.strip()
line_list = stripped_line.split()
file_contents.append(line_list)
file.close()
i = 0
for name in range(len(file_contents)):
i = i +1
if name == file_contents[i]:
table_3= [["Borrow Book","1"],
["Cancel Borrowing","2"]]
headers_3 = ["Details", "No."]
print(tabulate(table_3, headers_3, tablefmt = "grid"))
num = int(input("Please input 1 for confirmation of booking and 2 for canceling the booking: "))
file_contents[i] = changed_name
changed_name = str(changed_name)
if name == file_contents[i]:
IndexError: list index out of range
Example Of The File:
(books.txt)
Exile
Dancing In The Moonlight
Here is your complete solution . I hope it would help You
from tabulate import tabulate
name = str(input("Please input the books name that you would like to borrow: "))
file = open("books.txt", "r")
file_contents = [] #available books
for line in file:
line=line.strip()
file_contents.append(line)
file.close()
print("file content: ",file_contents)
i = 0
if name in file_contents:
table_3= [["Borrow Book","1"],["Cancel Borrowing","2"]]
headers_3 = ["Details", "No."]
print(tabulate(table_3, headers_3, tablefmt = "grid"))
num = int(input("Please input 1 for confirmation of booking and 2 for canceling the booking: "))
if(num==1):
try:
#user wants to withdraw that books so we've to remove that book from our available list of books
file_contents.remove(name)
#now we remove that book name from our available books.txt file
file=open("books.txt","w")
str1=" "
str1.join(file_contents)
file.write(str1)
print("Happy to serve you :-) visit again for more good books")
except Exception as e:
print("There is an error ",e)
else:
print("visit again for more good books")
You're missing with range keyword
Try this
for name in range(len(file_contents)):
#your work
I think you meant to iterate through the file_contents:
# code above elided
file.close()
for line in file_contents:
if name == line:
# following code elided
As the error says, an int cannot be iterable. How can you loop through 4?
The solution? Create a range of numbers:
for name in range(len(file_names)):
It would help if you posted the IndexError that you are getting.
And an example of the file you are opening?
What i think i could discover, is that you are using variable i als iterator, but i cannot find it in your loop.
Im trying to replace a cetain element in a txt file.
let say that if i find the name in telephonelist.txt, i want i to change the number to this person with the input value of newNumber.
let's say that name = Jens, then i want it to return 99776612 that is the tlf number to Jens, and then the input of 'newNumber' will replace this number. i am new to python.
def change_number():
while True:
try:
name = input('Name: ') #Enter name
newNumber = input('New number: ') # Wanted new number
datafile = open('telephonelist.txt')
if name in open('telephonelist.txt').read():
for line in datafile:
if line.strip().startswith(name):
line = line.replace(name,newNumber)
print('I found', name)
quit()
else:
print('I could not find',name+',','please try again!\n')
continue
except ValueError:
print('nn')
change_number()
This i telephonelist.txt
Kari 98654321
Liv 99776655
Ola 99112233
Anne 98554455
Jens 99776612
Per 97888776
Else 99455443
Jon 98122134
Dag 99655732
Siv 98787896
Load content, modify it, seek to beginning of the file, write the modified content again and then truncate the rest.
def change_number():
name = input('Name: ') #Enter name
newNumber = input('New number: ') # Wanted new number
with open('telephonelist.txt', 'r+') as file:
data = file.read().splitlines()
data = [line if not line.split()[0] == name else f"{name} {newNumber}" for line in data]
file.seek(0)
file.write("\n".join(data))
file.truncate()
change_number()
I'm trying to write a code that takes student names and saves into a file but i'm getting issue with opening file.
Below is the code snippet.
students = []
def get_students_titlecase():
students_titlecase = []
for student in students:
students_titlecase.append(student["name"].title())
return students_titlecase
def print_students_titlecase():
students_titlecase = get_students_titlecase()
print (students_titlecase)
def add_student(name, student_id):
student = {"name": name , "student_id": student_id}
students.append(student)
def save_file(student):
try:
f = open("students.txt", "a")
f.write(student + "\n")
f.close()
except Exception:
print("couldn't open the file")
def read_file():
try:
f = open("students.txt", "r")
for student in f.readlines():
add_student(student)
f.close()
except Exception:
print("couldn't read file")
read_file()
print_students_titlecase()
student_name = input("Enter the student name: ")
student_id = input("Enter the student_id: ")
add_student(student_name, student_id)
save_file(students)
Output:
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/arunyantrapragada/PycharmProjects/FirstProg/function.py
[]
Enter the student name: thomas
Enter the student_id: 456
couldn't open the file
Process finished with exit code 0
This is the reason a try/catch block is often ill-advised. Your error was not that the file could not be opened, but instead that this line was throwing an error:
f.write(student + "\n")
+ does not append a dictionary (student) and a string (\n). Your try/catch block is reporting this as an open file error.
I want to display the position of the name being searched for in a file. I know that I am missing something or maybe have named something incorrectly.
I am very new to Python and programming in general so please bear with me. Please explain what I have missed or done incorrectly so I may complete this program. Thanks for all help in advance.
try:
boyfile = open("boynames2014.txt", "r")
girlfile = open("girlnames2014.txt", "r")
except IOError:
print("Error: file not found")
gender = input("Enter gender (boy/girl): ")
if gender == "boy" or gender == "girl":
name = (input("Enter name to search for: "))
else:
print("Invalid gender")
if name in boyfile:
pos = boyfile.index(name)
print(name, "was ranked #", pos, "in 2014 for boy names")
else:
print(name, "was not ranked in the top 100 boy names for 2014")
if name in girlfile:
pos = girlfile.index(name)
print(name, "was ranked #", pos, "in 2014 for girl names")
else:
print(name, "was not ranked in the top 100 girl names for 2014")
boyfile.close()
girlfile.close()
When you are trying
if name in boyfile:
or the same for girlfile, you are trying to check for name variable name in an IOWrapper kind of element, it is not the list containing the file contents, it is just a reference to the file object here. you need to read the contents to a list
try:
boyfile = open("boynames2014.txt", "r")
girlfile = open("girlnames2014.txt", "r")
boyname_list = [line.strip() for line in boyfile] #read the content to a list
girlname_list = [line.strip() for line in girlfile] #read the content to a list
except IOError:
print("Error: file not found")
gender = input("Enter gender (boy/girl): ")
if gender == "boy" or gender == "girl":
name = (input("Enter name to search for: "))
if gender == "boy":
search_list = boyname_list
else:
search_list = girlname_list
if name in search_list:
pos = search_list.index(name)
print(name, "was ranked #", pos, "in 2014 for", gender," names")
else:
print(name, "was not ranked in the top 100", gender," names for 2014")
else:
print("Invalid gender")
boyfile.close()
girlfile.close()
You can try following to read the file and build list for boyfile and girlfile: For reference you can view link for reading file:
try:
with open("boynames2014.txt", "r") as f:
boyfile = []
for line in f:
boyfile.append(line.strip())
with open("girlnames2014.txt", "r") as f:
girlfile = []
for line in f:
girlfile.append(line.strip())
except IOError:
print("Error: file not found")
Or, you can also use following as referred in here:
try:
boyfile = [line.strip() for line in open('boynames2014.txt')]
girlfile = [line.strip() for line in open('girlnames2014.txt')]
except IOError:
print("Error: file not found")