【问题标题】:How to append to csv file before script is done running?如何在脚本完成运行之前附加到 csv 文件?
【发布时间】:2020-08-16 16:44:25
【问题描述】:

我目前正在创建一个登录系统,它将用户名和密码存储在一个文本文件中。

这是我的代码:

import csv

Brugere = open("D:\Filer\Programmering/Profiles.txt","r+",newline="\n")
writer = csv.writer(Brugere, delimiter=",")

print("Welcome to the chat app!")

Brugernavn = "" //means username
Kodeord = ""   // means password


def Signup(j,k):
    print("Welcome to sign up!\n Please enter your Username")
    j = input("")
    if j not in Brugere:
        print("Hello, " + j + ", please enter a password:")
        k = input("")
        line1 = [j,k]
        writer.writerow(line1)
        print("Great! Now you can sign in")
        Signin(Brugernavn, Kodeord)
    else:
        print("Username already taken! try again")
        Signup(Brugernavn, Kodeord)

def Signin(U,P):
    print("Welcome to sign in!")
    print("Do you already have an account?[y/n]")
    ans = input("")
    if ans == "n":
        print("You will now be redirected to sign up")
        Signup(Brugernavn, Kodeord)
    elif ans == "y":
        U = input("Username: ")
        if U in Brugere:
            P = input("Password: ")
            print("WELCOME")
        else:
            print("Invalid username, try again")
            Signin(Brugernavn, Kodeord)
    else:
        print("Please write 'y' or 'n'")
        Signin(Brugernavn, Kodeord)


Signin(Brugernavn, Kodeord)
Brugere.close()

当我运行它时,signup 函数正常工作,但是当调用登录函数时,它无法从文本文件中找到用户名和密码。我认为这是因为它们仅在脚本完成运行后才被附加。但是,'我不确定。

我一直在为这个 csv 文件而苦苦挣扎。我想拥有它 this 其中每一行都是一个列表,我可以在其中找到用户名和密码

我听说有人称它为“逗号分隔值”,但我不知道该怎么做。

【问题讨论】:

  • 您正在以读取模式打开文件,但尝试写入。使用"a" 作为模式(这意味着“附加”并打开它以进行写入,如果存在则附加到文件的末尾)。请参阅open() 函数的文档。使用csv 模块将自动在您传递给writerow() 的列表中的值之间添加逗号。
  • 非常感谢朋友!
  • 听起来很有帮助……不客气。顺便说一句,我还建议您阅读并开始关注PEP 8 - Style Guide for Python Code,尤其是关于naming conventions — 它将使您的代码更具可读性,尤其是对其他人而言。
  • 密码不应该被记录!!!在所有不安全的事情中,这是最糟糕的事情之一。密码也要用salt+hash保存,没有办法找回原来的密码。

标签: python csv


【解决方案1】:

TL;DR:

我怀疑最简单的解决方案是:

...
    if j not in brugere:
        ...
        writer.writerow(line1)
        brugere.flush()  # Flush pending changes to file.
        ...
...

但是,我注意到一些值得考虑的事情:

  • Python 帮助。您可以在交互式 Python 会话中获得有关 Python 方面的帮助:
python

> import csv
> help(csv)
  • 这种用例的 CSV 不是一个好主意。如果它是生产级的,请使用适当的数据库,如果您只是在本地玩耍以感受 Python,请使用 dict() 并存储为 JSON。即:
import json

username = "myuser"
password = "password"
filename = "data.json"

# Reads data. Requires file `data.json` to exist, with content `{}`.
with open(filename, "r") as data_stream:
    data = json.load(data_stream)

if username in data:
    print(f"User {username} exists.")
else:
    data[username] = password  # You'd usually hash and salt a password. It's a separate topic.

# Writes data to disk.
with open(filename, "w") as data_stream:
    data_stream.write(json.dumps(data, indent=2))  # Makes it look pretty on disk.
  • 请注意,open() 返回包装在类io.TextIOWrapper 中的stream(请参阅python -c "import io; help(io.TextIOWrapper)")。它基本上是获取所需数据的接口,而不是数据本身。例如,尝试open("test.txt").readlines() 实际从流中读取数据。请注意,流是消耗品。

  • 当您在流 Brugere 上调用 in 时,您正在调用 io.TextIOWrapper 类上的 __contains__() dunder 方法,但该方法未实现。但是 Python 是 Python,它返回 False(没有意义)。

  • CSV 界面非常简单:

import csv

filename = "test.txt"

f = open(filename, "w")
writer = csv.writer(f)
writer.write(["myuser", "password"])

# Flushes lines to file.
f.flush()
...

f.close()

【讨论】:

  • 这里的关键是您打算使用list 来完成地图工作。列表的键查找惩罚为 O(N),对于映射,它是 O(1)。进一步的地图设计为map 数据。即存储和检索归因于某些key 的数据。它还带有自动重复预防功能(这在您的 CSV 解决方案中会非常昂贵)。您真的想使用(某种形式的)地图。
【解决方案2】:

创建 CSV 就像编写一个字符串一样简单,每个值由指定字符分隔,顾名思义,通常是逗号。您实际上并不需要 csv 库。

您的注册方法如下所示:

def Signup(j,k):
    print("Welcome to sign up!\n Please enter your Username")
    j = input("")
    if j not in Brugere:
        print("Hello, " + j + ", please enter a password:")
        k = input("")
        line1 = [j,k]
        # Write a string with a comma between the values   
        Brugere.write("{}, {}\n".format(j, k))
        print("Great! Now you can sign in")
        Signin(Brugernavn, Kodeord)
    else:
        print("Username already taken! try again")
        Signup(Brugernavn, Kodeord)

话虽如此,使用 CSV 将操作数据存储在应用程序中对我来说意义不大。请参阅下面的 signup 的修改版本,使用 SQLite,它更加健壮且易于使用:

import sqlite3
con = sqlite3.connect('brugere.db')
cur = con.cursor()

# Create a user table with bruger and kodeord
# I added an extra field for when the user was created as well 
# which defaults to the date and time the user was created 
cur.execute("""create table if not exists brugere
               (brugernavn text, 
                kodeord text,
                dato_oprettet TIMESTAMP  DEFAULT CURRENT_TIMESTAMP)""")

con.close()


def signup():
    
    con = sqlite3.connect('brugere.db')
    cur = con.cursor()
    
    with con:
        print("Please enter your Username")
        bruger = input()
        cur.execute("select brugernavn from brugere where brugernavn =?", [bruger])
        
        bruger_eksisterer = cur.fetchone()
        
        if bruger_eksisterer:
            print("Username already taken! Try again")
            # Signup(Brugernavn, Kodeord)
        else:    
            print("Hello, " + bruger + ", please enter a password:")
            kodeord = input()
            
            try:
                cur.execute("insert into brugere (brugernavn, kodeord) values (?, ?)", (bruger, kodeord))
                print("Great! Now you can sign in")
            except sqlite3.Error as Err:
                print("Couldn't add user.\nError: {}".format(Err))         
                # Signin(Brugernavn, Kodeord)        
    
    con.close()

signup()    

修改signin 应该是直截了当的,但我会把这部分留给你。

【讨论】:

  • 非常感谢 :D 这真的很有帮助!呃,还有一件事。你知道我如何检查密码是否与用户名匹配吗?因此,如果它与用户名在同一行。我猜该行上的用户名是 [0],而该行上的密码是 [1]。但是我该怎么做呢?
  • 我也可以去试试 SQLite。但现在我真的很想完成这项工作:)
  • python 有一个 cvs 模块。如果我的密码是 `"","","",\n",像你这样写 cvs 会失败
猜你喜欢
  • 2013-06-12
  • 1970-01-01
  • 1970-01-01
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
  • 2015-05-02
  • 2012-05-12
  • 1970-01-01
相关资源
最近更新 更多