birthday reminder app: function doesn't display

Viewed 220

I'm new to programming, and I was trying to build this birthday reminder app without following a specific tutorial, but rather trying to figure it out by myself, but I am stuck.

The first function adds birthdays to .txt file, no problem. But with the second, whether I try to retrieve birthday data from birthday_dict or from the file, the function just doesn't run.

For the second function, I tried to adjust this https://www.geeksforgeeks.org/birthday-reminder-application-python/, but it still doesn't work.

If anybody can help me with that, it would be great. Thanks!

import datetime
from datetime import date, timedelta


birthday_dict = {}
def add_to_log():
    name = input("Name: ")
    date_str = input("Birthday (day/month) :")
    birthday_dict.update({name: date_str})
    with open('./venv/birthday_log.txt', mode='a') as birthday_log:
        file = birthday_log.write(f'\n {name}:{date_str}')
    print ('Birthday added!')

def reminder():
    file = open('birthday_log.txt', 'r')
    today = date.today()
    today.strftime("%d/%m")
    flag = 0
    for line in file:
        if today in file:
            line = line.split(':')
            flag = 1
            print (f'Today is {line[1]}\'s birthday!')
2 Answers

The script contains a couple of mistakes. I will try to address them one-by-one. I numbered them for reference.

  • [1] You don't use the same filename on both functions. In one place you use ./venv/birthday_log.txt', and in another place you use birthday_log.txt` (without the subfolder).

    This can be solved by moving the filename into either a global variable or a function argument. Especially when you begin programming I highly discourage using global variables, so lets use a function argument (see below)

  • [2] When using date.today() you get today's date as a variable of type "date". But when you want to compare that with text, you need to convert it to "str". You are doing that correctly by calling .strftime(...) on it. But that call will return the string-value. It will not modify the existing date object. So you need to store the result in a new variable so you can use it later.

  • [3] When testing if today's date is found, you are using the in operator with a date-object (as mentioned in [2]) and a file object which will not work. We need to use "strings" on both sides of the in operator. On the left side we can use the new variable we created in [2] and on the right side, we can use line which represents the current line we are looping over.

A few more tips:

  • You can use print(type(variable)) to see the type of a variable
  • Instead of using birthday_dict.update({name: date_str}) you can also simply write birthday_dict[name] = date_str

Little "exercises"

  • Take the two lines I wrote at the very end of the script and move them into on "main" function. That way you could use one single variable for the filename and remove the duplication of the value. You could use a global variable as well, but as mentioned before it is best avoided. Wrapping the lines in a "main" function will resolve that issue.

  • On global variables: You have one global variables birthday_dict. Think about how you could make that a "local" variable. Tip: It is very similar to the changes made to the filenames.

import datetime
from datetime import date, timedelta


birthday_dict = {}
def add_to_log(filename):
    name = input("Name: ")
    date_str = input("Birthday (day/month) :")
    birthday_dict.update({name: date_str})

    # [1] Using a variable here makes it easier to ensure we only specify the
    # filename once
    with open(filename, mode='a') as birthday_log:
        file = birthday_log.write(f'\n {name}:{date_str}')
    print ('Birthday added!')

def reminder(filename):
    # [1] Using a variable here makes it easier to ensure we only specify the
    # filename once
    file = open(filename, 'r')
    today = date.today()
    # [2] After creating a reference for "today", you need to store the
    # "string" conversion in a new variable and use that later
    today_str = today.strftime("%d/%m")
    flag = 0
    for line in file:
        # [3] You want to check that the date you need is contained in the
        # line, not the file object
        if today_str in line:
            line = line.split(':')
            flag = 1
            print (f'Today is {line[1]}\'s birthday!')


add_to_log("birthday_log.txt")
reminder("birthday_log.txt")

For viewing all the lines in a file you need to run .readlines() from the variable with open() and that will make a list as so:

file = open("test.txt", "r")
lines = file.readlines() # lines = ['hello','test']

The lines variable will be a list and you can do stuff like this:

for line in lines:
    print(line)

Also, you probably want to write for today in line, in your second function.

Related