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?