在文本文件中编辑密码的最简单方法 Python

Simplest method to edit password in text file Python

我有以下代码,它经历了逐行读取文件、将其转换为列表、编辑该列表中的字段的阶段,但最后阶段是重写原始文件,用这个包括编辑。

我会对建议 easiest/simplest 修复(不使用 pandas/numpy 等)并使用提供的原始代码的答案感兴趣。

我目前的算法包括必须创建一个包含所有记录的新文件(链接到该用户名的记录除外),然后将此列表写入其中。这看起来很费力而且没有必要。非常感谢收到任何解决方案!

任务在评论中解释得更清楚:

代码

 """ ==============TASK
    ALLOW THE USER TO CHANGE OR EDIT THEIR PASSWORD
    1. Search for any given username
    2. Edit the password field for that given username
    3. Save the new updated username and password to file / updated
    """

    import csv
    def main():
        #1. This code snippet asks the user for a username and then allows them to change password for that record
        updatedlist=[]
        with open("fakefacebook.txt",newline="") as f:
          reader=csv.reader(f)
          print("CHANGE PASSWORD?!")
          username=input("Enter the username for the required user:")
          for row in reader: #for every row in the file
              for field in row:

                    if field==username: #if a field is == to the required username
                        updatedlist.append(row) #add each row, line by line, into a list called 'udpatedlist'
                        newpassword=input("Enter new password")
                        #print(updatedlist[0][1]) (this is how we get at the password field, noting it is a nested list)
                        updatedlist[0][1] = newpassword #set the field for password to the new password


          updatepassword(updatedlist)

    def updatepassword(updatedlist):
        with open("fakefacebook.txt","w",newline="") as f:
            Writer=csv.writer(f)
            Writer.writerows(updatedlist)
            print("File has been updated")


    main()

注意:目前代码只允许用户更改密码(这在列表中已更改)。该列表仅包含该用户的记录。它将这条记录(使用更改后的密码)覆盖到文本文件,而不是所需的(原始文件内容 + 仅此编辑)

文件内容

username,password,email,no_of_likes
marvR,pass123,marv@gmail.com,400
smithC,open123,cart@gmail.com,200
blogsJ,2bg123,blog@gmail.com,99

需要输出

如果测试使用:marvR 将密码更改为:boo123

新文件应包含:

username,password,email,no_of_likes
marvR,**boo123**,marv@gmail.com,400
smithC,open123,cart@gmail.com,200
blogsJ,2bg123,blog@gmail.com,99

任何 comments/explanations 关于教授初学者的最佳方法也将不胜感激。 Python 没有开发某种模块来使编辑文件中的字段比这个 3 步算法更容易,这似乎很奇怪,这对初学者来说真的很困难(我说的是 13-14 岁的孩子)锻炼身体

这里可以使用字典代替列表数据结构。字典将值映射到用户定义的键而不是整数。因此,与其说遍历列表以找到正确的用户名,不如简单地将整个文件存储在数据结构中并使用随机访问来更改所需的用户名:

from collections import defaultdict
def main():
        inputDict=defaultdict(string)
        with open("fakefacebook.txt",newline="") as f:
          reader=csv.reader(f)
          for row in reader: #for every row in the file
              line = row.split(',') #splits the CSV row into an array

              #sets the key to be the username, and everything else 
              #to be value, and then adds it to inputDict
              inputDict[line[0]] = line[1:] 

          print("CHANGE PASSWORD?!")
          username=input("Enter the username for the required user:")
          newpassword=input("Enter new password")
          if (inputDict[username]):
              inputDict[username] = newpassword
          else: print("No such username!")


          updatepassword(inputDict)

您必须修改 updatepassword() 才能使用 dictionary

也应考虑@VPfB 的回答。

这只是更新记录而不替换文件中现有记录的答案。但是有更好的方法可以做到这一点。

import csv

def main():
    #1. This code snippet asks the user for a username and then allows them to change password for that record
    updated_list = []
    cached_list = []

    with open("fakefacebook.txt", newline="") as f:
        reader = list(csv.reader(f)) # Convert iterable to list to make things easier.
        print("CHANGE PASSWORD?!")
        username=input("Enter the username for the required user: ")
        cached_list = reader # store copy of data.

        for row in reader: #for every row in the file
            for field in row:  
                if field == username: #if a field is == to the required username
                    updated_list.append(row) #add each row, line by line, into a list called 'udpated_list'
                    newpassword = input("Enter new password: ")
                    #print(updatedlist[0][1]) (this is how we get at the password field, noting it is a nested list)
                    updated_list[0][1] = newpassword #set the field for password to the new password

        update_password(updated_list, cached_list)

def update_password(updated_list, cached_list):
    for index, row in enumerate(cached_list):
        for field in row:
            if field == updated_list[0]:
                cached_list[index] = updated_list # Replace old record with updated record.

    with open("fakefacebook.txt","w", newline="") as f:
        Writer=csv.writer(f)
        Writer.writerows(cached_list)
        print("File has been updated")


main()

到目前为止,其中一个相关问题尚未得到解决。您提到了"teaching beginners",所以请将此答案视为对其他答案的补充。

编辑密码文件等文件时,不应像此处提供的代码那样覆盖原始文件。如果由于任何原因(包括磁盘已满或断电)导致写入失败,则可能会丢失数据。更重要的是,文件应该始终处于一致状态,即任何人都不应该看到部分写入的文件。

要做到这一点:

  1. 从文件中读取数据
  2. 在内存中修改根据需要处理数据
  3. 将结果保存到一个新的临时文件,关闭该文件(with 自动执行),您甚至可能想调用 os.fsync()
  4. 如果有任何错误,请删除临时文件并在此处停止
  5. 只有在一切正常的情况下,自动 将临时文件重命名为原始文件,最好使用 os.replace() (Python 3.3+)。一步完成原子操作。

更新:修改了 updatepassword 代码并添加了一些注释:

FILE = "fakefacebook.txt"

def updatepassword(updatedlist):
    # create the tempfile in the same directory (os.replace requires the same filesystem)
    tempfile = FILE + ".tmp"
    try:
        # "x" = fail with the FileExistsError if the file exists already
        with open(tempfile, "x", newline="") as f:
            writer = csv.writer(f)
            writer.writerows(updatedlist)
            f.flush()               # flush the internal buffers
            os.fsync(f.fileno())    # write to disk
        os.replace(tempfile, FILE)
        print("File has been updated")
        tempfile = None     # tempfile renamed
    except FileExistsError:
        print("Another copy is running or stale tempfile exists")
        tempfile = None     # tempfile does not belong to this process
    except OSError as err:
        print("Error: {}".format(err))
    finally:
        if tempfile:
            try:
                os.unlink(tempfile)
            except OSError:
                print("Could not delete the tempfile")