首页 > 解决方案 > 在 Python 中写入文件但仅替换某些数据实例

问题描述

我有一段代码,它应该替换逗号分隔文件中的特定字段。在下面的示例中,它替换了分配任务的用户。当前用户是文件中的第一个字段。在代码的前一部分中,我确定了要编辑的文件的相关行(存储为“edit_line”变量)。

代码基本上贯穿每一行。如果它不是我要编辑的行,我只需按原样重写该行。但如果它是我要编辑的行,我使用 REPLACE 函数来更改字段,在本例中为用户名(它被变量“diff_user”的值替换)。

with open("tasks.txt",'w') as f:
    # Go through file line by line and rewrite the data:
    for i, line in enumerate(data):
        # If relevant line (selected task) replace necessary field:
        if i == edit_line:
            f.writelines(line.replace(line.strip().split(", ")[0], diff_user))
        # For other lines, just replace with same data again
        else:
            f.writelines(line)

除了一个逻辑错误之外,这非常有效,但我是一个新手,直到它意外发生才想到它。

问题当然是 replace 函数将替换该行中存在的与line.strip().split(", ")[0].

因此,如果我有一个名为“ADMIN”的当前用户,并且稍后在同一行中有文本“ADMIN”(例如在任务描述中),那么这两个都将被新用户名替换,而不仅仅是当前用户名存在于该行的第一个字段中的用户名。

我宁愿不做大的重写。有什么方法可以修改当前代码以仅限制写入行或替换函数以查看行中的特定字段而不是每个实例?我知道用replace我可以说只有第n个实例应该被替换,但问题是我不知道要替换的有效项目是第1个、第2个还是第11个......(第一个字段的用户名字段是只是一个示例,但也可以替换文件中的后续字段)。

如果没有捷径,我该如何重写逻辑来处理这个问题?

更新:这是整个功能,因此有人可以执行它。这段代码实际上是课程的一部分:

def edit_task(task_number):
    class ExistException(Exception):  # Custom exception used later
        pass
    choice = ""  # used later
    edit_line = int(task_number) - 1  # Line of file to be edited (starts at 0, hence the minus 1)
    tf = open("tasks.txt","r")  # Open task file for reading first
    data = tf.readlines()
    print(f"EDIT TASK {task_number}:\n")

    # Split the selected task (edit_line) into separate fields:
    task_un = data[edit_line].strip().split(", ")[0]  # Stores username
    task_title = data[edit_line].strip().split(", ")[1]  # Stores title
    task_desc = data[edit_line].strip().split(", ")[2]  # Stores description
    task_cd = data[edit_line].strip().split(", ")[3]  # Stores create date
    task_dd = data[edit_line].strip().split(", ")[4]  # Stores due date
    task_ci = data[edit_line].strip().split(", ")[5]  # Stores completion indicator

    # Print out task detail:
    print(f"Task {task_number}: {task_title}")
    print(f"Description:    {task_desc}")
    print(f"Assigned to:    {task_un}")
    print(f"Created on:     {task_cd}")
    print(f"Due Date:       {task_dd}")
    print(f"Completed?:     {task_ci}")
    print("")


    # Check if already done, print accordingly and return to previous menu:
    if task_ci == 'Yes':
        print("\nThis task is already completed, and cannot be edited.\n")
        view_mine()

    # Give user different options to edit task:
    edit_option = input(f"Type 'DONE' to mark task {task_number} as completed.\n"
    "Type 'USER' to assign the task to someone else.\n"
    "Type 'DATE' to change the due date.\n"
    "Type any other key to go back to the main menu:\n-->").lower()

    # User selected to mark as completed:
    if edit_option == 'done':
        task_ci = 'Yes'  # change variable
        with open("tasks.txt",'w') as f:
            # Go through file line by line and rewrite the data:
            for i, line in enumerate(data):
                # If relevant line (selected task) replace necessary field:
                if i == edit_line:
                    f.writelines(line.replace(line.strip().split(", ")[5], "Yes"))
                # For other lines, just replace with same data again
                else:
                    f.writelines(line)
            tf.close()
            # Print updated task:
            print(f"Task {task_number} marked as completed:\n")
            print(f"Task {task_number}: {task_title}")
            print(f"Description:    {task_desc}")
            print(f"Assigned to:    {task_un}")
            print(f"Created on:     {task_cd}")
            print(f"Due Date:       {task_dd}")
            print(f"Completed?:     {task_ci}")   
            print("")

            option = input("Type '-1' to go back to the Main Menu, "
            "or any other key to exit.\n--> ").lower()
            if option == '-1':
                mainMenu()
            else:
                print("Goodbye")
                exit()

    # User selected to assign to someone else:
    elif edit_option == 'user':
        while True:
            try:
                # Refer to ELSE portion below. if username does NOT exist, user can try again 
                #(stored as choice, and this becomes input)
                if choice != "":  
                    diff_user = choice
                else: # if choice is still null, then this is first time entry attempt:
                    print("Enter the username of the person the "
                    "task should be assigned to:")
                    print (f"Available users: {users}")
                    diff_user = input("\n-->").lower()
                # Loop through file to check if user exists. Must count it at least once:
                if diff_user in users:
                    task_un = diff_user
                    with open("tasks.txt",'w') as f:
                        # Go through file line by line and rewrite the data:
                        for i, line in enumerate(data):
                            # If relevant line (selected task) replace necessary field:
                            if i == edit_line:
                                f.writelines(line.replace(line.strip().split(", ")[0], diff_user))
                            # For other lines, just replace with same data again
                            else:
                                f.writelines(line)
                    tf.close()
                    # Print updated task:
                    print(f"Task {task_number} assigned to '{diff_user}'\n")
                    print(f"Task {task_number}: {task_title}")
                    print(f"Description:    {task_desc}")
                    print(f"Assigned to:    {task_un}")
                    print(f"Created on:     {task_cd}")
                    print(f"Due Date:       {task_dd}")
                    print(f"Completed?:     {task_ci}")   
                    print("")

                    option = input("Type '-1' to go back to the Main Menu, "
                    "or any other key to exit.\n--> ").lower()
                    if option == '-1':
                        mainMenu()
                    else:
                        print("Goodbye")
                        exit()
                # If username does NOT exist, throw error and ask user to go to registration, OR
                # try enter username again:
                else:  
                    print("This user does not exist. Press 'R' to register them, or enter a"
                    " different username:")
                    print (f"Available users: {users}")
                    choice = input("\n-->").lower()  # store username and go back to start if loop
                    if choice == 'r':            #... unless they chose, "R" the go to Registration
                        reg_user()
                    else:
                        raise ExistException
            except ExistException:
                pass

    # User selected to change due date:
    elif edit_option == 'date':
        new_due_date = date_val()  # Calls function to enter & validate date, & returns variable
        with open("tasks.txt",'w') as f:
            # Go through file line by line and rewrite the data:
            for i, line in enumerate(data):
                # If relevant line (selected task) replace necessary field:
                if i == edit_line:
                    f.writelines(line.replace(line.strip().split(", ")[4], new_due_date))
                # For other lines, just replace with same data again
                else:
                    f.writelines(line)
        tf.close()
        print(f"Due Date \'{task_dd}\' changed to '{new_due_date}'.")
        option = input("Type '-1' to go back to the Main Menu, "
        "or any other key to exit.\n--> ").lower()
        if option == '-1':
            mainMenu()
        else:
            print("Goodbye")
            exit()
    else:
        print("Returning to Main Menu\n")
        mainMenu()

您需要参考我在此处命名的文件并提供以下几行:

1]任务.txt

admin, Register Users with taskManager.py, Use taskManager.py to add the usernames and passwords for all users that will be using this program., 10 Oct 2019, 20 Dec 2019, Yes
admin, Assign initial tasks, Use taskManager.py to assign each non-admin team member with appropriate tasks, 10 Oct 2019, 25 Dec 2019, Yes
gerhard, Test program, run through all program functions to test it, 11 Dec 2019, 27 Dec 2019, Yes
admin, Add comments to program, make sure entire .py file has comments for easy reading, 11 Dec 2019, 12 Jan 2020, No
diana, UAT, do user acceptance testing on the program, 11 Dec 2019, 15 Mar 2020, No
test, Program Sign-off, Department Manager to sign off on UAT so program can be implemented, 12 Dec 2019, 31 Mar 2020, No
gerhard, Example task, This is just an example of what a task description might look like with a duplicate gerhard, 12 Dec 2019, 14 Jun 2021, No
diana, water the plants, every week all the plants must be watered, 12 Dec 2019, 12 Jan 2019, No
admin, Test blah , blah blah blah, 24 Dec 2019, 12 Feb 2020, No
gerhard, print all, All tasks to be printed and filed, 26 Dec 2019, 13 Feb 2021, No

2]用户.txt

admin, adm1n
test, t3st
blah, kkijh
gerhard, test123#
gerhardl, 555%%%
diana, test123
maya, 12test
jannie, password!
sannie, password123
zuma, ???
harley, test11

标签: pythonfilereplace

解决方案


我知道你说过你不想改变你的代码。但是我能想到的解决方案是使用熊猫。

您可以读取将其存储到数据框中的 csv 文件,然后您可以访问您的用户名列并仅替换其值。会是这样的。

import pandas as pd

# Read the csv
df = pd.read_csv('my_old_file.csv')

# Update the desired row
df.loc[edit_line,'username'] = diff_user

# Save the new dataframe
df.to_csv('replaced_value.csv')

推荐阅读