Day 055 - Project 55 : Backup Before Auto Saving

If you have any questions, comments or issues with this project please post them here!

please i tried using the os.path.join() to store my file in the backup directory but its not working I don’t know what the problem could be. Also I would like to know what os.popen() does

Hi @ValenciaFaith can you please post a link to the Repl you are having issues with?

Thank you i have solved the problem

1 Like

Hello
I’m having the same problem I had in Project 51. My code is giving error.(I didn’t solve that problem in day 51, so it still exists.)

link to repl: https://replit.com/@SUMAYDOHARE/Day55100Days#main.py

Please help

Hi @SUMAYDOHARE thanks for your post.

I forked your Repl and it seemed to work. I noticed that you had [] in the hhhhh file this time. Did you find that fixed the issue or did you add other code?

Hi
Once again, thanks for your help.
I visited the Forum of Day 51 and found the solution to my problem there

I get an error when my list is empty.
Is there a way to make the .eval() function skip when the file is empty?

image

Here is my code:

import os, time, random

to_do_list = []
files = os.listdir()
file = "todolist.txt"


def autoload():
  if file in files:
    f = open(file, "r")
    to_do_list = eval(f.read())
    f.close()
  else:
    f = open(file, "w")
    f.close()


def autosave():
  f = open(file, "w")
  f.write(str(to_do_list))
  f.close()


def backup():
  if "back up/" not in files:
    f = os.mkdir("back up")
  else:
    back_up_name = "backup" + str(random.sample(range(0, 100000),6))
    back_up_file = os.path.join("back up/", back_up_name)
    f = open(back_up_file, "w")
    f.write(str(to_do_list))
    f.close()


def find_index(item):
  x = to_do_list.index(item)
  return int(x)


def menu():
  print()
  select = input("""select option:\n
  'view' To-Do list
  'add' to To-Do List
  'remove' from To-Do List
  'edit' an entry on To-Do List
  'clear' to delete all on To-Do List\n
  >""").lower()
  if select[0] == "v":
    printList()
  elif select[0] == "a":
    item = input("\nwhat do you want to add to your To-Do List?\n").upper()
    if item in to_do_list:
      print("already on To-Do List!")
    else:
      to_do_list.append(item)
  elif select[0] == "r":
    item = input(
      "\nwhat do you want to remove from your To-Do List?\n").upper()
    confirm = input(f"\nAre you sure you want to remove {item}? (y/n)\n")
    if confirm == "y" and item in to_do_list:
      to_do_list.remove(item)
    elif confirm == "no":
      menu()
    else:
      print()
      print(f"{item} was not found on your To-Do List!")
  elif select[0] == "e":
    item = input("\nwhich entry do you want to change?\n").upper()
    new_item = input("\nwhat's the new entry gonna be?\n").upper()
    if item in to_do_list:
      x = find_index(item)
      to_do_list[x] = new_item
      print(f"{item} changed to {new_item}")
    else:
      print()
      print(f"{item} was not found on your To-Do List!")
  elif select[0] == "c":
    to_do_list.clear()
    print("To-Do-List hast been cleared!")
  else:
    print()
    print()
    print(f"{menu()} is not a valid option! Try again.")
  time.sleep(2)


def printList():
  print("To-Do List")
  print()
  for index in range(len(to_do_list)):
    print(f"{index+1:2}: {to_do_list[index]}")
  print()
  time.sleep(2)


while True:
  print("TO-DO LIST")
  autoload()
  menu()
  os.system("clear")
  backup()
  autosave()

One way could be

try:
  #eval statement
except:
  pass

But as i said in the past, i discourage from using eval. Especially when using things like flask so starting to avoiding it even in simpler projects is a good idea

Thanks! This works…
Well for someone who is taking this course I have no other knowledge than the eval() so far. So I have to go with it.

However, I have another problem now :sob:
Every time I run my program again, it wipes my to-do-list file and overwrites it with the stuff from the current run.

I had this issue before, because I used autosave() subroutine. When I use the code normally (not as sub-routine) it works - I don’t understand why!? I think it’s cleaner to put it in a sub-routine, but why is it not working then!?

import os, time, random

to_do_list = []
files = os.listdir()
file = "todolist.txt"


def autoload():
  try:
    if file in files:
      f = open(file, "r")
      to_do_list = eval(f.read())
      f.close()
    else:
      f = open(file, "w")
      f.close()
  except:
    pass

def autosave():
  f = open(file, "w")
  f.write(str(to_do_list))
  f.close()


# check back_up_exists


def backup():
  try:
    if "back up" not in files:
      f = os.mkdir("back up")
    else:
      back_up_name = "backup_" + str(random.sample(range(0, 100000),1))
      back_up_file = os.path.join("back up/", back_up_name)
      f = open(back_up_file, "w")
      f.write(str(to_do_list))
      f.close()
  except:
    pass


def find_index(item):
  x = to_do_list.index(item)
  return int(x)


def menu():
  print()
  select = input("""select option:\n
  'view' To-Do list
  'add' to To-Do List
  'remove' from To-Do List
  'edit' an entry on To-Do List
  'clear' to delete all on To-Do List\n
  >""").lower()
  if select[0] == "v":
    printList()
  elif select[0] == "a":
    item = input("\nwhat do you want to add to your To-Do List?\n").upper()
    if item in to_do_list:
      print("already on To-Do List!")
    else:
      to_do_list.append(item)
  elif select[0] == "r":
    item = input(
      "\nwhat do you want to remove from your To-Do List?\n").upper()
    confirm = input(f"\nAre you sure you want to remove {item}? (y/n)\n")
    if confirm == "y" and item in to_do_list:
      to_do_list.remove(item)
    elif confirm == "no":
      menu()
    else:
      print()
      print(f"{item} was not found on your To-Do List!")
  elif select[0] == "e":
    item = input("\nwhich entry do you want to change?\n").upper()
    new_item = input("\nwhat's the new entry gonna be?\n").upper()
    if item in to_do_list:
      x = find_index(item)
      to_do_list[x] = new_item
      print(f"{item} changed to {new_item}")
    else:
      print()
      print(f"{item} was not found on your To-Do List!")
  elif select[0] == "c":
    to_do_list.clear()
    print("To-Do-List hast been cleared!")
  else:
    print()
    print()
    print(f"{menu()} is not a valid option! Try again.")
  time.sleep(2)


def printList():
  print("To-Do List")
  print()
  for index in range(len(to_do_list)):
    print(f"{index+1:2}: {to_do_list[index]}")
  print()
  time.sleep(2)


while True:
  print("TO-DO LIST")
  autoload()
  menu()
  os.system("clear")
  backup()
  autosave()

Well, you are opening the file for writing with option “w”, this means that it will overwrite the file.
You can open the file with option “a” and this will append the new data to the file.

However (and I have not looked at your code), if you always read all data, add data, and write all data … append is wrong.

Also take the good habit of passing the file name to the function instead of using a global variable or constant (btw constants should be all capitals …)

1 Like

ok yes that was a stupid copy paste error… However… still wipes my list each time!! :sob:
Again, so far I have just been following the course by David, so let’s forget about the “best-practice” coding for now and focus on why the code doesn’t do what I want it to do :thinking:

What is that you need to do? If you want to append just make sure there is nothing that open the files in overwrite mode.

The thing is, when I don’t use the whole auto-save and auto-load code as a subroutine (all the code is directly in the while True loop) it works fine and the file is correctly read every time.
However, if I use this code in several sub-routines, that’s when it overwrites my file every time I run the program. I fail to understand what makes the difference here.

This is the working code now: (compare it to the one above)

import os, time, random

to_do_list = []
files = os.listdir()
file = "todolist.txt"

def find_index(item):
  x = to_do_list.index(item)
  return int(x)


def menu():
  print()
  select = input("""select option:\n
  'view' To-Do list
  'add' to To-Do List
  'remove' from To-Do List
  'edit' an entry on To-Do List
  'clear' to delete all on To-Do List\n
  >""").lower()
  if select[0] == "v":
    printList()
  elif select[0] == "a":
    item = input("\nwhat do you want to add to your To-Do List?\n").upper()
    if item in to_do_list:
      print("already on To-Do List!")
    else:
      to_do_list.append(item)
  elif select[0] == "r":
    item = input(
      "\nwhat do you want to remove from your To-Do List?\n").upper()
    confirm = input(f"\nAre you sure you want to remove {item}? (y/n)\n")
    if confirm == "y" and item in to_do_list:
      to_do_list.remove(item)
    elif confirm == "no":
      menu()
    else:
      print()
      print(f"{item} was not found on your To-Do List!")
  elif select[0] == "e":
    item = input("\nwhich entry do you want to change?\n").upper()
    new_item = input("\nwhat's the new entry gonna be?\n").upper()
    if item in to_do_list:
      x = find_index(item)
      to_do_list[x] = new_item
      print(f"{item} changed to {new_item}")
    else:
      print()
      print(f"{item} was not found on your To-Do List!")
  elif select[0] == "c":
    to_do_list.clear()
    print("To-Do-List hast been cleared!")
  else:
    print()
    print()
    print(f"{menu()} is not a valid option! Try again.")
  time.sleep(2)


def printList():
  print("To-Do List")
  print()
  for index in range(len(to_do_list)):
    print(f"{index+1:2}: {to_do_list[index]}")
  print()
  time.sleep(2)


while True:
  print("TO-DO LIST")
  try:
    if file in files:
      f = open(file, "r")
      to_do_list = eval(f.read())
      f.close()
    else:
      f = open(file, "r")
      f.close()
  except:
    pass
  menu()
  os.system("clear")
  try:
    if "back up" not in files:
      f = os.mkdir("back up")
    else:
      back_up_name = "backup" + str(random.sample(range(0, 100000),1))
      back_up_file = os.path.join("back up/", back_up_name)
      f = open(back_up_file, "w")
      f.write(str(to_do_list))
      f.close()
  except:
    pass
  f = open(file, "w")
  f.write(str(to_do_list))
  f.close()

First f all you can make things a bit cleaners by using the try except only for the command that might cause the error

f = open(file, "r")
try:
    if file in files:
      to_do_list = eval(f.read())
except:
    pass
f.close()
1 Like

Than I am still lost.
Your code loads the data into a variable, adda data and dumps the entire data into the same file always replacing its previous content. What is the error?

I dont get an error as such. It’s just using code as a subroutine vs. using the code right in the while True loop.
When I use the code as sub-routine (see my code above) it doesn’t seem to load the file properly and clears it every time.

it’s not so much about the main code and how the files are being writen, but the fact that the program works differently depending on whether I use subroutines or not.

ok, i think your issue is a scope issue … as i mentioned before try to pass variables and not assume they are global.
instead of doing something like autoload() and autosave(), do autoload(to_do_list) and autosave(to_do_list) (and probably for back up also). I hope this gives you enough to understand without me being more explicit …

1 Like

I’m kind of disappointed with the tutorial video for this lesson as it doesn’t really explain the code nor does the solution video say it.
I’m having an issue with backing up the file… I get the cp: target ‘backups/backup728423.txt’ is not a directory message but the file isn’t created.
here’s my code, hope someone can help me figure this out

import os,random, time

toDo = []
fileExists = True

try:
  f = open("to do.txt","r")
  toDo = eval(f.read())
  f.close()
except:
  fileExists = False
  
# ________________________________________________
def prettyPrint():
  for row in toDo: 
    for item in row:
      print(f"{item:^10} | ", end="")
#    print(f"{row[0] :^15} {row[1] :^15}", end="")
    print()
# ________________________________________________
def addTask():
  time.sleep(1)
  item = input("What do you want to add: ")
  due_by = input("When is it due by? ")
  priority = input("Priority (high, medium or low)? \n")
  toDo.append([item, due_by, priority])
# ________________________________________________
def viewTask():
  time.sleep(1)
  option = input("Do you want to view:\n\n 1.all tasks\n 2.priority tasks \n\n").strip()
  print()
  if option == "1":  # PRINT ALL TASKS
    print()
    prettyPrint()
  elif option == "2":  # check what priority task to print
    print()
    priority = input("Filter by priority (High,  Medium or Low) \n\n").strip().lower()
    print()
    for row in toDo:
      if priority in row:
        for item in row:
          print(f"{item:^10} | ", end="")
          # prints the each item inside the row
        print() #print high priority tasks
# ________________________________________________
def removeTask():
  time.sleep(1)
  item = input("What do you want to remove from the list? \n> ")
  for row in toDo:
    if item in row:
      toDo.remove(row)
# ________________________________________________
def editTask():
  time.sleep(1)
  item = input("What do you want to edit? \n> ")
  #  CHECK IF ALREADY IN TABLE
  item_found = False
  for row in toDo:
    if item in row:
      item_found = True
    if not item_found:
      print("Couldn't find that")
      return
    #  REMOVE ROW AND INSERT NEW
    for row in toDo:
      if item in row:
        toDo.remove(row)
  item = input("New task: ")
  due_by = input("Due by? ")
  priority = input("Priority (high, medium or low)? \n")
  toDo.append([item, due_by, priority])
        
while True:
  print("To Do List Manager\n")
  print('Do you want to view, add, edit or remove an item from the to do list?\n\nType "exit" to leave the TDL Manager.')
  print()
  #  menu input for options
  menu = input("1. View\n2: Add\n3. Remove\n4. Edit\n5. Delete list\n\n> ").lower()
  print()
  if menu == "1":  # VIEW
    viewTask()
    time.sleep(2)
  elif menu =="2":  # ADD
    addTask()
  elif menu == "3":  # REMOVE
    removeTask()
  elif menu == "4":   # EDIT
    editTask()
  elif menu == "5":  # DELETE LIST
    check = input("Are you sure you want to delete the list?!\ny/n\n")
    if check == "y":
      toDo = []
      print("List deleted")
  elif menu == "exit":  # EXIT THE PROGRAM
    os.system("clear")
    break
  time.sleep(1)
  os.system("clear")

  if fileExists:
    try:
      os.mkdir("backups")
    except:
      pass
    name = f"backup{random.randint(1,1000000)}.txt"
    os.popen(f"cp to do.txt backups/{name}")

  f = open("to do.txt", "w") 
  f.write(str(toDo)) 
  f.close()

Hi, I copied your code into a python file and when I run it I get no error … could you share the repl where the error occurs?