If you have any questions, comments or issues with this project please post them here!
For anyone who gets an unexpected EOF error with the Day 51 example code and are struggling…
The file you are trying to write to needs to be populated with an empty list []
beforehand.
Thought I’d post the solution here to hopefully help someone out.
For file auto-saves: why don’t we use “a+” instead of “w”? It seems like we’re trying to append items to the list, not rewrite the whole list. I know it works, just curious as to why it does.
Autosave is designed to use as little code as possible, if we used a+ it would append after the []
of the list. Originally I’d used this as a quick way for students to memorise code snippets to use in exams but it’s a neat way of dumping the contents of a list and being able to use things like .remove
and have the changes propogate.
Hi,
I have a problem with the auto-save trick.
The file doesn’t get updated in the first loop but gets updated with the first task after the second loop. I printed the list to test that everything works. But I still don’t understand why the file doesn’t get updated on the first go ?
I will keep scratching my mind to understand what’s going on, but I would be open to some help from the community. Thanks !
import os, time
todo = []
#f = open("todo.txt", 'r')
#todo = eval(f.read())
#f.close()
def prettyprint(sublist):
print(f"""
{'Task':<10}{'->':^10}{sublist[0]:>10}
{'Due time':<10}{'->':^10}{sublist[1]:>10}
{'Priority':<10}{'->':^10}{sublist[2]:>10}""")
while True:
#os.system('clear')
title = "YOUR TODO LIST"
print(f"{title:^6}")
print()
menu = input('add, view, edit or remove an item ? > ').strip().lower()
if menu == "add":
item = input("what to do ? > ").strip().lower()
due = input("when is it due ? > ").strip().lower()
priority = input(
"is the priority high, medium or low ? > ").strip().lower()
todo.append([item, due, priority])
print('the task has been added to the list, select view to check it out')
time.sleep(3)
elif menu == "view":
type_of_view = input(
"Do you want to view high, medium or low priority, or all items ? > "
).strip().lower()
print()
if type_of_view[0] == 'a':
print("ALL YOUR TASKS")
for task_number in range(len(todo)):
prettyprint(todo[task_number])
elif type_of_view[0] == 'h':
print("HIGH PRIORITY TASKS")
for task_number in range(len(todo)):
if todo[task_number][2] == 'high':
prettyprint(todo[task_number])
elif type_of_view[0] == 'm':
print("MEDIUM PRIORITY TASKS")
for task_number in range(len(todo)):
if todo[task_number][2] == 'medium':
prettyprint(todo[task_number])
elif type_of_view[0] == 'l':
print("LOW PRIORITY TASKS")
for task_number in range(len(todo)):
if todo[task_number][2] == 'low':
prettyprint(todo[task_number])
print()
input("press any key to return to the menu >")
elif menu == "edit":
item_to_edit = input("which task do you want to edit ? > ").strip().lower()
for sub_todo in range(len(todo)):
if item_to_edit == todo[sub_todo][0]:
print(
f"the task you selected is to {todo[sub_todo][0]} before {todo[sub_todo][1]} with a {todo[sub_todo][2]} priority."
)
info_to_edit = input(
"do you want to change the task, the time or priority ? > ").strip(
).lower()
if info_to_edit == 'task':
new_task = input("what's the new task ? > ").strip().lower()
todo[sub_todo][0] = new_task
elif info_to_edit == 'time':
new_time = input("what's the new due time ? > ").strip().lower()
todo[sub_todo][1] = new_time
elif info_to_edit == 'priority':
new_priority = input("what's the new priority ? > ").strip().lower()
todo[sub_todo][2] = new_priority
print("the information has been changed, returning to the menu")
time.sleep(2.5)
elif menu == "remove":
item_to_remove = input("which task did you finish ? > ").strip().lower()
for sub_todo in range(len(todo)):
if todo[sub_todo][0] == item_to_remove:
todo.pop(sub_todo)
print("Well done ! The list is updated, select view to check it out.")
time.sleep(3)
break
else:
print("instruction unclear, please input add, view, edit or remove")
time.sleep(3)
print(todo) # test: the todo list is up to date
f = open("to.do", "w")
f.write(str(todo))
f.close
Well, I still can’t figure out what’s wrong.
To be clear let me give an example.
1/ I select add from the menu and enter the task > run, tomorrow, high.
2/ The program runs and my empty list todo is now printed [[run, tomorrow, high]]
3/ Here comes the issue, the f.write(str(todo)) does not write anything to the file ?!
4/ The loop is done and I add another task > read, today, medium.
5/ Now the todo is printed [[run, tomorrow, high], [read, today, medium]]
6/ And in the file appear the first task only [run, tomorrow, high]
I think it has to do with how I constructed my add block but still don’t get what’s wrong.
If you could give it a go and tell me if you encounter the same issue. Thanks !
The problem might be that you can not saving the list to the file and also the flie name is to.do
but it is meant to be a .txt
file.
This is my code that saves the tasks.
import os, time
todo = []
#f = open("todo.txt", 'r')
#todo = eval(f.read())
#f.close()
def prettyprint(sublist):
print(f"""
{'Task':<10}{'->':^10}{sublist[0]:>10}
{'Due time':<10}{'->':^10}{sublist[1]:>10}
{'Priority':<10}{'->':^10}{sublist[2]:>10}""")
while True:
#os.system('clear')
title = "YOUR TODO LIST"
print(f"{title:^6}")
print()
menu = input('add, view, edit or remove an item ? > ').strip().lower()
if menu == "add":
item = input("what to do ? > ").strip().lower()
due = input("when is it due ? > ").strip().lower()
priority = input(
"is the priority high, medium or low ? > ").strip().lower()
todo.append([item, due, priority])
print('the task has been added to the list, select view to check it out')
f = open("todo.txt", "w")
f.write(str(todo))
f.close
time.sleep(3)
elif menu == "view":
type_of_view = input(
"Do you want to view high, medium or low priority, or all items ? > "
).strip().lower()
print()
if type_of_view[0] == 'a':
print("ALL YOUR TASKS")
for task_number in range(len(todo)):
prettyprint(todo[task_number])
elif type_of_view[0] == 'h':
print("HIGH PRIORITY TASKS")
for task_number in range(len(todo)):
if todo[task_number][2] == 'high':
prettyprint(todo[task_number])
elif type_of_view[0] == 'm':
print("MEDIUM PRIORITY TASKS")
for task_number in range(len(todo)):
if todo[task_number][2] == 'medium':
prettyprint(todo[task_number])
elif type_of_view[0] == 'l':
print("LOW PRIORITY TASKS")
for task_number in range(len(todo)):
if todo[task_number][2] == 'low':
prettyprint(todo[task_number])
print()
input("press any key to return to the menu >")
elif menu == "edit":
item_to_edit = input("which task do you want to edit ? > ").strip().lower()
for sub_todo in range(len(todo)):
if item_to_edit == todo[sub_todo][0]:
print(
f"the task you selected is to {todo[sub_todo][0]} before {todo[sub_todo][1]} with a {todo[sub_todo][2]} priority."
)
info_to_edit = input(
"do you want to change the task, the time or priority ? > ").strip(
).lower()
if info_to_edit == 'task':
new_task = input("what's the new task ? > ").strip().lower()
todo[sub_todo][0] = new_task
elif info_to_edit == 'time':
new_time = input("what's the new due time ? > ").strip().lower()
todo[sub_todo][1] = new_time
elif info_to_edit == 'priority':
new_priority = input("what's the new priority ? > ").strip().lower()
todo[sub_todo][2] = new_priority
print("the information has been changed, returning to the menu")
f = open("todo.txt", "w")
f.write(str(todo))
f.close
time.sleep(2.5)
elif menu == "remove":
item_to_remove = input("which task did you finish ? > ").strip().lower()
for sub_todo in range(len(todo)):
if todo[sub_todo][0] == item_to_remove:
todo.pop(sub_todo)
print("Well done ! The list is updated, select view to check it out.")
time.sleep(3)
break
else:
print("instruction unclear, please input add, view, edit or remove")
time.sleep(3)
print(todo) # test: the todo list is up to date
f = open("todo.txt", "w")
f.write(str(todo))
f.close
Thanks a lot !
My understanding was that the extension of the file doesn’t matter, but I apparently does !
Cheers
I don’t know, but it’s possible it’s because Python doesn’t know that that file extension should be read as text (since different files are read differently depending on their extension).
because f.close() is missing brackets. so the file never gets properly closed and the change remains in limbo until the 2nd loop.
Hello All,
Please help me figure out print statement in the “delete” function. I want to add if input is not in list element - print something. I am not sure how to structure the if-else. I tried multiple ways.
import random, os, time
myEvents = []
f = open("calendar.txt", "r")
myEvents = eval(f.read())
f.close()
def inputIdea():
os.system("clear")
idea = input("Input your idea: ")
row = [idea]
myEvents.append(row)
print(idea, "added!")
print()
time.sleep(2)
os.system("clear")
def generateIdea():
os.system("clear")
idea = random.choice(myEvents)
print()
print("Your random idea is: ", *idea)
time.sleep(2)
os.system("clear")
def deleteIdea():
os.system("clear")
idea_to_delete = input("What idea you would like to delete?: ")
#I want to add an "else" statement if idea_to_delete is not in the list and print something, but if I add it, it will not find my idea_to_delete if it is not the first item in list as it starts to loop one by one - please help where to put else statemnt
for row in myEvents:
if idea_to_delete in row:
myEvents.remove(row)
print()
print(idea_to_delete, "is removed form your idea list.")
time.sleep(2)
os.system("clear")
while True:
print("Idea Storage")
print()
usr_choice = input("'1' Enter your idea. \n'2' Display a random idea. \n'3' Delete idea. \n > ")
if usr_choice == "1":
inputIdea()
elif usr_choice == "2":
generateIdea()
elif usr_choice == "3":
deleteIdea()
f = open("calendar.txt", "w")
f.write(str(myEvents))
f.close()
I’m not very sure about it myself - but i suppose you could try checking the ideea user is inputting against the list you are trying to remove it from. But here … i’ve checked your code and i’ve made a few modifications:
for the first at the beginning we check if the file is empty or not … so you won’t get errors. If it exists or not you should add try, except - but i don’t know what operators have you worked with until now.
then i have removed the row = [ideea] line - that was unnecessary!
then the for loop was really making a mess in your list :)) so i’ve removed it!
there are a few commented lines - about os.system(“clear”) - but those are not working properly on my spyder IDE and i usually don’t use it.
I’m a beginner too - so don’t know a lot yet … but started to realize how little i actually know :)))
Here is your code sort of updated:
# -*- coding: utf-8 -*-
"""
Created on Wed Feb 15 09:44:53 2023
@author: soreen
"""
import random, os, time
myEvents = []
f = open("calendar.txt", "r")
contents = f.read()
if len(contents) > 0:
myEvents = eval(contents)
f.close()
def inputIdea():
# os.system("clear")
idea = input("Input your idea: ")
# row = [idea]
myEvents.append(idea)
print(idea, "added!")
print()
time.sleep(2)
# os.system("clear")
def generateIdea():
# os.system("clear")
idea = random.choice(myEvents)
print()
print("Your random idea is: ", *idea)
time.sleep(2)
# os.system("clear")
def deleteIdea():
# os.system("clear")
idea_to_delete = input("What idea you would like to delete?: ")
#I want to add an "else" statement if idea_to_delete is not in the list and print something, but if I add it, it will not find my idea_to_delete if it is not the first item in list as it starts to loop one by one - please help where to put else statemnt
if idea_to_delete not in myEvents:
print("No way Jose, you need to first have that ideea!")
elif idea_to_delete in myEvents:
myEvents.remove(idea_to_delete)
print()
print(idea_to_delete, "is removed form your idea list.")
time.sleep(2)
# os.system("clear")
while True:
print("Idea Storage")
print()
usr_choice = input("'1' Enter your idea. \n'2' Display a random idea. \n'3' Delete idea. \n'4' Exit > ")
if usr_choice == "1":
inputIdea()
elif usr_choice == "2":
generateIdea()
elif usr_choice == "3":
deleteIdea()
elif usr_choice == "4":
f = open("calendar.txt", "w")
f.write(str(myEvents))
f.close()
break
Well I hope you manage I’m struggling myself!
Thank you very much
In the solution suddenly David uses the eval() function (“todo = eval(f.read())”).
It is unclear to me what exactly that does? I’ve tried searching, but didn’t found an explanation I’ve comprehend… Perhaps someone here can explain this?
Thx in advance!
To be honest I would advise you not to do that and use Eval on files. It is a lazy to load files into lists and alike, and it is a serious security risk.
Why is it a security risk?
Because when you use eval on a file, the command will evaluate the file. This can actually be a program itself …