Python Forum
writing list to csv file problem
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
writing list to csv file problem
#1
im making a task reminder that will send emails and sms reminding of tasks and events. my problem that im stuck with is with saving the data. i chose csv as it is easy to maintain and construct using the pandas library. the problem is where i am extending my send_date_list even though the variable itself is a list, whilst looking inside the csv file i notice that that cell in question is a list in quotation marks meaning that it writes the value as a string and not a list. obviously i need it to be saved as a list in order to search or delete specific entries. an example of my code follows



def save_info():
    names_list,due_dates_list,send_date_list,end_date_list,desc_list,phone_number_list,email_address_list=[],[],[],[],[],[],[]
    """Save the entered reminder information if valid."""
    try:
        df = pd.read_csv("data.csv")
    except FileNotFoundError:
        with open("data.csv", "w") as file:
            writer = csv.writer(file)
            writer.writerow(["name", "date", "description", "phone number","email address","recurring"])
        df = pd.DataFrame(columns=["name", "date", "description", "phone number","email address","recurring"])
    client=kickbox.Client(api_key)
    kbx=client.kickbox()
    send_date = send_date_ent.get()
    end_date=end_date_ent.get()
    due_date=reminder_date_ent.get()
    to_email_address=email_ent.get()
    response=kbx.verify(to_email_address)
    if response.body['result']!="undeliverable":
        if check_date(send_date):
            if check_date(due_date):
                if check_date(end_date):
                    frequency=simpledialog.askinteger(title="Task frequency",prompt="How many days should the task occur?")

                    name = name_ent.get().title()
                    name_parts = name.split(" ")
                    if len(name_parts) < 2:
                        messagebox.showerror(title="Ooooooops",
                                             message="You have not entered a first and last name!!\nPlease try again!!")
                        return

                    desc = description_ent.get()
                    phone_number = phone_ent.get()
                    pattern=r'^\d{11}'
                    if len(str(phone_number))!=11 or not re.match(pattern,phone_number):
                        messagebox.showerror(title="OOOOOOps", message="You have not entered a valid phone number!!\n"
                                                                       "Please enter a valid UK phone number \n"
                                                                       "The phone number should be 12 digits long!!\n")
                        return
                    if check_alphabetical(name):

                        if check_alphabetical(desc):


                            if messagebox.askyesno(title="Save this information?",
                                                   message=f"On the {due_date} {name_parts[1]}, {name_parts[0]} should be reminded to {desc}!!"
                                                           f"A text message will be sent on {send_date}\n "
                                                           f"Their phone number is {phone_number}\n"
                                                           f"Their email address is {to_email_address}\n"
                                                           f"Do you want to save this information?\n"):
                                saved_data=df.to_dict("records")
                                if var1.get()==1:
                                    end_date_index=dates_list_starting_from_today.index(end_date)
                                    send_date=dates_list_starting_from_today[:end_date_index:frequency]
                                    send_date_list.extend(send_date)
                                    recurring=True
                                    print(send_date_list)
                                else:
                                    due_dates_list.append(due_date)
                                    send_date=send_date_ent.get()
                                    send_date_list.append(send_date)
                                    due_date=reminder_date_ent.get()
                                    recurring=False



                                names_list.append(name)

                                desc_list.append(desc)
                                phone_number_list.append(phone_number)
                                email_address_list.append(to_email_address)
                                saved_data.append({"name":names_list,"send date":send_date_list,"due date":due_dates_list,"description":desc_list,"phone number":phone_number_list,"email address":email_address_list,"recurring":recurring})

                            df2=pd.DataFrame(saved_data)
                            df2.to_csv("data.csv", index=False)

                            send_date_ent.delete(0, END)
                            reminder_date_ent.delete(0,END)
                            name_ent.delete(0, END)
                            description_ent.delete(0, END)
                            phone_ent.delete(0, END)
                            email_ent.delete(0,END)
                            end_date_ent.delete(0,END)
            else:
                messagebox.showerror(title="OOOOOops",
                                             message="You have entered a date set in the past!!\nPlease remedy this mistake and try again!!")
        else:
            messagebox.showerror(title="OOOOOops",
                                         message="You have entered a date set in the past!!\nPlease remedy this mistake and try again!!")
    else:
        messagebox.showerror(title="OOOOOOPs",message="The email address you entered does not exist!!\nPlease correct the mistake and submit again!!\n")
Reply
#2
If you are using pandas, why are you using a CSV writer? Pandas knows how to read and write CSV files. Your save_info function should be:
events_dataframe.to_csv(csv_filename)
I think csv files and pandas are poor fits for your problem. I would use a json file and dictionaries, or maybe a dataclass. Pandas does a poor job acting like a list.
import pandas as pd
from datetime import datetime
import json


date_format = "%m/%d/%Y"


def add_event(events):
    events.append({
        "name": input("Name: "),
        "description": input("Description: "),
        "date": datetime.strptime(input("Date: "), date_format),
    })


def print_events(events):
    temp = events.copy()
    for event in temp:
        event["date"] = event["date"].strftime(date_format)
    print(pd.DataFrame(temp))


def load_events(filename):
    try:
        with open(filename, "r") as file:
            events = json.load(file)
        for event in events:
            event["date"] = datetime.strptime(event["date"], date_format)
        return events
    except IOError:
        return []


def save_events(filename, events):
    temp = events.copy()
    for event in temp:
        event["date"] = event["date"].strftime(date_format)
    with open(filename, "w") as file:
        json.dump(events, file)


events = load_events("events.json")
while True:
    choice = input("1: Add event\n2: Print events\n3: Quit\n> ")
    if choice == '1':
        add_event(events)
    elif choice == '2':
        print_events(events)
    elif choice == '3':
        break
save_events("events.json", events)
Reply
#3
Quote:json might not be the best choice for on-disk formats; The trouble it has with appending data is a good example of why this might be. Specifically, json objects have a syntax that means the whole object must be read and parsed in order to understand any part of it.

Fortunately, there are lots of other options. A particularly simple one is CSV; which is supported well by python's standard library. The biggest downside is that it only works well for text; it requires additional action on the part of the programmer to convert the values to numbers or other formats, if needed.

Another option which does not have this limitation is to use a sqlite database, which also has built-in support in python. This would probably be a bigger departure from the code you already have, but it more naturally supports the 'modify a little bit' model you are apparently trying to build.

If I were collecting information like this and storing it in a database, I would use MySQL and collect the data in an html form.

You can access MySQL from Python easily.
Reply
#4
I don't see this being an "on disk format" type application. With reoccurring events, expired events, and adding events that may fall anywhere within the range of existing events there is going to be a lot of shuffling in the order of event records. Appending events to the end of a file is not going to a requirement.

A database would work, but I think most queries will have to pull up the entire table. Queries, the biggest advantage of a database, may not be useful for the kinds of comparisons that must be made to find all events scheduled for a particular day.

But the choice of file format or database is not the issue here. The problem is that save_info() is a poorly designed function. You should have a function that collects information from the user, and a different function for making the information persistent. When you describe what a function does, "and" should not appear in the description. save_info() pulls information from the form, validates the information, adds the information to the dataframe, and saves the dataframe to a CSV file. That is two to many commas and one to many "and"s
Reply
#5
(Jun-30-2024, 03:55 AM)deanhystad Wrote: If you are using pandas, why are you using a CSV writer? Pandas knows how to read and write CSV files. Your save_info function should be:
events_dataframe.to_csv(csv_filename)
I think csv files and pandas are poor fits for your problem. I would use a json file and dictionaries, or maybe a dataclass. Pandas does a poor job acting like a list.
import pandas as pd
from datetime import datetime
import json


date_format = "%m/%d/%Y"


def add_event(events):
    events.append({
        "name": input("Name: "),
        "description": input("Description: "),
        "date": datetime.strptime(input("Date: "), date_format),
    })


def print_events(events):
    temp = events.copy()
    for event in temp:
        event["date"] = event["date"].strftime(date_format)
    print(pd.DataFrame(temp))


def load_events(filename):
    try:
        with open(filename, "r") as file:
            events = json.load(file)
        for event in events:
            event["date"] = datetime.strptime(event["date"], date_format)
        return events
    except IOError:
        return []


def save_events(filename, events):
    temp = events.copy()
    for event in temp:
        event["date"] = event["date"].strftime(date_format)
    with open(filename, "w") as file:
        json.dump(events, file)


events = load_events("events.json")
while True:
    choice = input("1: Add event\n2: Print events\n3: Quit\n> ")
    if choice == '1':
        add_event(events)
    elif choice == '2':
        print_events(events)
    elif choice == '3':
        break
save_events("events.json", events)

i use both csvwriter and pandas library approaches to practice using both of them. plus with the csvwriter approach i get to just add the headers. and clear all of the data. i chose list of dictionaries (dataframes/csv) because it is easy to get a hold of data by something like the following


from tkinter import messagebox

import pandas as pd
current_time = datetime.now().strfttime("%d%m%Y")
df=pd.read_csv("data.csv")
saved_data=df.to_dict("records")
for entry in saved_data:
    if ent["send_date"]==current_time:
        if messagebox.askyesorno(title="Save information",message=f"On {ent['send_date']} {ent['name']} should be reminded to {ent['task']}\nShould i send this sms?")
so for my purposes a csv file is more fitting seeing as with json file i would have a problem with choosing which value to use as the key. if i were to use json i would maybe use the send date as a key and the value as a dictionary that has name,task,phone number and email address key and value pairs. but seeing how there may be multiple tasks to remind about in the same day then the json file approach loses its appeal.
if you can please help me with the subject at hand (writing string instead of list of strings in a csv cell) i would greatly appreciate it.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Bug Writing in a document problem IOHANNES 4 1,220 Oct-26-2022, 08:58 PM
Last Post: IOHANNES
  Writing string to file results in one character per line RB76SFJPsJJDu3bMnwYM 4 1,620 Sep-27-2022, 01:38 PM
Last Post: buran
  Writing to json file ebolisa 1 1,116 Jul-17-2022, 04:51 PM
Last Post: deanhystad
  Problem with "Number List" problem on HackerRank Pnerd 5 2,297 Apr-12-2022, 12:25 AM
Last Post: Pnerd
  Writing to External File DaveG 9 2,818 Mar-30-2022, 06:25 AM
Last Post: bowlofred
  problem writing dataframe to oracle aliyesami 4 2,818 Sep-25-2021, 11:20 PM
Last Post: SamHobbs
  Writing to file ends incorrectly project_science 4 2,929 Jan-06-2021, 06:39 PM
Last Post: bowlofred
  Writing unit test results into a text file ateestructural 3 5,023 Nov-15-2020, 05:41 PM
Last Post: ateestructural
  Writing to file in a specific folder evapa8f 5 3,671 Nov-13-2020, 10:10 PM
Last Post: deanhystad
  list from a data file problem Marre 3 2,896 Sep-22-2020, 07:55 AM
Last Post: Marre

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020