最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

pandas - Python DataFrame structure breaks when appending the File - Stack Overflow

programmeradmin3浏览0评论

I am trying to get user inputs to create a file where users can store website, username, and password in table format whenever users hit a button. I made the function below, and it looks okay to me. However, when a user enters the second and third entries, the data frame structure is broken. Any idea why it happens? You may see the print result each time adding a row to my data.

Code:

from tkinter import *
import pandas as pd
import os

def save_password():
    website_name = input("Website: ")
    username = input("Username: ")
    password = input("Password: ")
    # password_details = f"website: {website_name};username: {username};password: {password}"
    input_entries_dict = {"Website": [website_name],
                          "Username/Email": [username],
                          "Password": [password]}
    input_entries_df = pd.DataFrame(input_entries_dict)
    if not os.path.isfile("MyPassword_test.txt"):
        input_entries_df.to_csv("MyPassword_test.txt", index=False)
        print(input_entries_df)
    else:
        data = pd.read_csv("MyPassword_test.txt")
        data = data._append(input_entries_df, ignore_index=True, sort=True)
        print(data)
        data.to_csv("MyPassword_test.txt", sep=";", index=False)

save_password()

Outputs for each time:

First entry: ALL FINE
  Website Username/Email Password
0  d32d23        f7324f2  f3223f2

Second Entry: Column names are shifted
       Password Username/Email  Website
0       f3223f2        f7324f2   d32d23
1  ddwefddsfds5       32fwefw5  48sfd4s

Third Entry:Colum of "Password;Username/Email;Website" created!
  Password Password;Username/Email;Website Username/Email    Website
0      NaN          f3223f2;f7324f2;d32d23            NaN        NaN
1      NaN   ddwefddsfds5;32fwefw5;48sfd4s            NaN        NaN
2   154152                             NaN      f32f23f23  2f23f2332

I am trying to get user inputs to create a file where users can store website, username, and password in table format whenever users hit a button. I made the function below, and it looks okay to me. However, when a user enters the second and third entries, the data frame structure is broken. Any idea why it happens? You may see the print result each time adding a row to my data.

Code:

from tkinter import *
import pandas as pd
import os

def save_password():
    website_name = input("Website: ")
    username = input("Username: ")
    password = input("Password: ")
    # password_details = f"website: {website_name};username: {username};password: {password}"
    input_entries_dict = {"Website": [website_name],
                          "Username/Email": [username],
                          "Password": [password]}
    input_entries_df = pd.DataFrame(input_entries_dict)
    if not os.path.isfile("MyPassword_test.txt"):
        input_entries_df.to_csv("MyPassword_test.txt", index=False)
        print(input_entries_df)
    else:
        data = pd.read_csv("MyPassword_test.txt")
        data = data._append(input_entries_df, ignore_index=True, sort=True)
        print(data)
        data.to_csv("MyPassword_test.txt", sep=";", index=False)

save_password()

Outputs for each time:

First entry: ALL FINE
  Website Username/Email Password
0  d32d23        f7324f2  f3223f2

Second Entry: Column names are shifted
       Password Username/Email  Website
0       f3223f2        f7324f2   d32d23
1  ddwefddsfds5       32fwefw5  48sfd4s

Third Entry:Colum of "Password;Username/Email;Website" created!
  Password Password;Username/Email;Website Username/Email    Website
0      NaN          f3223f2;f7324f2;d32d23            NaN        NaN
1      NaN   ddwefddsfds5;32fwefw5;48sfd4s            NaN        NaN
2   154152                             NaN      f32f23f23  2f23f2332
Share Improve this question asked 2 days ago schamane34schamane34 131 silver badge3 bronze badges New contributor schamane34 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 1
  • don't use private methods – juanpa.arrivillaga Commented 2 days ago
Add a comment  | 

2 Answers 2

Reset to default 2

The confusion is caused by writing the .CSV with a ; separator but ignoring this on reading. Use:

    else:
        data = pd.read_csv("MyPassword_test.txt")
        data = pd.concat([data, input_entries_df], ignore_index=True)
        print(data)
        data.to_csv("MyPassword_test.txt", index=False)

Your core issue here is that in the case of an existing file, you rewrite the file with a non-default separator sep=";" and thus:

  • the first entry works (using commas)
  • the second entry works reading commas but writing semi-colons
  • the third (and subsequent) entry fails reading expecting commas but finding none.

The fix is to use a standard separator. Either accept the default everywhere or override it everywhere.

In any case, you should stop using ._append() and switch to pandas.concat()

I would likely use the csv package here rather than pandas but if you are keen on pandas, I might suggest.

import pandas
import os

def save_password(website_name, username, password):
    password_file = "MyPassword_test.txt"   # I might think about passing this in as a fourth argument
    new_record= {
        "Website": [website_name],
        "Username/Email": [username],
        "Password": [password]
    }

    ## --------------
    ## If the file does not exist, create it with the required columns
    ## Note: use columns=list(new_record.keys()) if you want to be explicit
    ## --------------
    if not os.path.isfile(password_file):
        pandas \
            .DataFrame(columns=new_record) \
            .to_csv(password_file, index=False)
    ## --------------

    ## --------------
    ## Since we now know the file exists, we can always append the new record
    ## --------------
    pandas \
        .concat([
            pandas.read_csv(password_file),
            pandas.DataFrame(new_record)
        ]) \
        .to_csv(password_file, index=False)
    ## --------------

## --------------
## I try to avoid asking for input in methods that could accept arguments
## --------------
website_name = input("Website: ")
username = input("Username: ")
password = input("Password: ")
save_password(website_name, username, password)
## --------------
发布评论

评论列表(0)

  1. 暂无评论