accessing .txt file updating a list and performing actions on that list

38 Views Asked by At

I have the below section of code which if the user enters "gr" will run.

What I am trying to do is run over the tasks.txt file, append, strip, and split it to reports[] so I can then access each part of the list as needed to update the 2 dictionaries with the relevant info. I will then be opening and writing this info to 2 new .txt files (task_overview.txt + user_overview.txt)

If this doesn't make any sense I'm sorry but I have been struggling with this for ages and I am also very new.

tasks.txt looks like this:

user;Task;description of task;due date;entered date;completed

sam;asdfgg;gfdsa;2024-12-12;2024-03-09;No
admin;werty;ytrew;2024-12-12;2024-03-09;No
sam;plkju;ujklp;2024-02-12;2024-03-09;No
admin;qwaszx;xzsawq;2023-12-12;2024-03-09;No
sam;finish cap2;make the code more user friendly;2024-03-16;2024-03-11;No

gr code :

elif menu == 'gr':
        
        # creating dictionary with values for task_overview file
        stat_dict_task_overview = {
                    "Tasks": 0,
                    "Completed": 0,
                    "Uncompleted": 0,
                    "Overdue": 0,
                    "Percentage Incomplete": 0,
                    "Percentage Overdue": 0
                    }
        
        # creating dictionary with values for user_overview file
        stat_dict_user_overview = {
                    "Users": 0,
                    "Tasks": 0,
                    "Name": 0,
                    
                         }
       
        reports = []
       
        with open("tasks.txt", "r") as task:
         
            # This code updates the dictionary as needed
            for line in enumerate(task):
                stat_dict_task_overview["Tasks"] += 1


            
            # From this point on nothing gets updated to the dictionary
            reports = task.readlines()       
            for line in task:
               reports.append(line.strip().split(";"))
         
            for line in task:
                if reports[-1] == "Yes":
                    stat_dict_task_overview["Completed"] += 1
                else:
                    stat_dict_task_overview["Uncompleted"] += 1
       

                if reports[3] < str(datetime.today()):
                    stat_dict_task_overview["Overdue"] += 1
       
                
        print(reports)
        print(stat_dict_task_overview) 

What I am trying to do is run over the tasks.txt file, append, strip, and split it to reports[] so I can then access each part of the list as needed to update the 2 dictionaries with the relevant info. I will then be opening and writing this info to 2 new .txt files (task_overview.txt + user_overview.txt)

1

There are 1 best solutions below

0
Edo Akse On

I went a bit overboard with the answer, but I've seen this particular question pass by a couple of times with slight differences. I've quite heavily commented my code, and I've split the things into separate functions.

Main thing is, is that you're using a CSV file with a semicolon separator. Using the standard python CSV module, and specifically the csv.DictReader() will make your life a lot easier. It basically turns the CSV file into a dict (as the method name suggests) and then it becomes very easy to deal with.

import csv
from datetime import datetime
# pprint is only imported to make the ouput at the bottom look nice
from pprint import pprint


def loadfile(csvfilename: str) -> dict[list]:
    users = {}
    # easy reading of file as a CSV file
    # it skips over empty lines, and uses the first line as the dict key names
    with open(csvfilename) as csvfile:
        reader = csv.DictReader(csvfile, delimiter=";")
        for row in reader:
            # remove the name and use it as a key in the users dict
            name = row.pop("user")
            if name not in users:
                # add new user
                users[name] = [row]
            else:
                # update existing user
                users[name].append(row)
    return users


def get_stat_user_overview(users: dict[list]) -> dict:
    tasks = 0
    name = 0  # no idea what this is supposed to be
    for user in users:
        # just count the length of the tasklist and add to tasks
        tasks += len(user)
    usercount = len(users)
    # you can just generate and return a dict without assigning it
    # to a variable first
    return {
        "Tasks": tasks,
        "Users": usercount,
        "Names": name
    }


def get_stat_task_overview(users: dict[list]) -> dict:
    # set initial dict to zeros
    result = {
        "Tasks": 0,
        "Completed": 0,
        "Uncompleted": 0,
        "Overdue": 0,
    }
    today = datetime.now() # only set this once to reduce the function calls
    for user in users.values():
        for task in user:
            # add task count
            result['Tasks'] += 1
            # check if task completed
            if task['completed'] == 'No':
                result['Uncompleted'] += 1
                # only check for overdue for the uncompleted items
                # it's also safer to turn the string into a datatime object
                # and then do a comparison between datetime objects
                if datetime.strptime(task['due date'], '%Y-%m-%d') < today:
                    result['Overdue'] += 1
            else:
                result['Completed'] += 1
    # do the percentage calculations
    result["Percentage Incomplete"] = result['Uncompleted'] / result['Tasks'] * 100
    result["Percentage Overdue"] = result['Overdue'] / result['Tasks'] * 100
    return result


csvfilename = "tasks.txt"
users = loadfile(csvfilename)
pprint(users, indent=4)
print('-----')
user_stats = get_stat_user_overview(users)
pprint(user_stats, indent=4)
print('-----')
task_stats = get_stat_task_overview(users)
pprint(task_stats, indent=4)

resulting output:

{   'admin': [   {   'Task': 'werty',
                     'completed': 'No',
                     'description of task': 'ytrew',
                     'due date': '2024-12-12',
                     'entered date': '2024-03-09'},
                 {   'Task': 'qwaszx',
                     'completed': 'No',
                     'description of task': 'xzsawq',
                     'due date': '2023-12-12',
                     'entered date': '2024-03-09'}],
    'sam': [   {   'Task': 'asdfgg',
                   'completed': 'No',
                   'description of task': 'gfdsa',
                   'due date': '2024-12-12',
                   'entered date': '2024-03-09'},
               {   'Task': 'plkju',
                   'completed': 'No',
                   'description of task': 'ujklp',
                   'due date': '2024-02-12',
                   'entered date': '2024-03-09'},
               {   'Task': 'finish cap2',
                   'completed': 'No',
                   'description of task': 'make the code more user friendly',
                   'due date': '2024-03-16',
                   'entered date': '2024-03-11'}]}
-----
{'Names': 0, 'Tasks': 8, 'Users': 2}
-----
{   'Completed': 0,
    'Overdue': 3,
    'Percentage Incomplete': 100.0,
    'Percentage Overdue': 60.0,
    'Tasks': 5,
    'Uncompleted': 5}