如何替换.txt文件数据库中的dict的特定项

时间:2017-06-01 16:26:51

标签: python database

我想使用.txt文件来存储应用程序的API令牌,但是如果找到了替换API密钥/令牌的话,我就会陷入困境,如果它在文件中找到的话。这是代码尝试(Python 3.5)

data_to_save = {}
data_to_save['savetime'] = str(datetime.datetime.now())[:19]
data_to_save['api_key'] = key_submitted
data_to_save['user'] = uniqueid
api_exists = False
user_exists = False
with open("databases/api_keys.txt", 'r+') as f:
    database = json.loads(f.read())
    for i in database:
        if i['api_key'] == key_submitted:
            send_text_to_user(userid, "[b]Error: That API key is already in use.[/b]", "red")
            api_exists = True
        if i['user'] == uniqueid:
            user_exists = True
    if user_exists == True:
        if api_exists = True:
            send_text_to_user(userid, "[b]Error: Your API key was already saved at another time.[/b]", "red")
        else:
            f.write(json.dumps(data_to_save)) #Here, StackOverflow
            send_text_to_user(userid, "[b]Okay, I replaced your API key.[/b]", "green")
    f.close()
if user_exists == False:
    writing = open("databases/api_keys.txt", 'a')
    writing.write(json.dumps(data_to_save))
    writing.close()

我也想知道这是否是最好的方法,或者代码可以优化以及如何。

谢谢,它已经完成了。最终代码:

data_to_save = {'savetime': str(datetime.datetime.now())[:19], 'api_key': key_submitted, 'user': uniqueid}
with open("databases/api_keys.txt", 'r') as f:
    database = json.loads(f.read())
    for i in database:
        if i['user'] == uniqueid:
            database.remove(i)
        if i['api_key'] == key_submitted:
            send_text_to_user(userid, "[b]Error: That API key is already in use.[/b]", "red")
            api_exists = True
            break
    if not api_exists:
        database.append(data_to_save)
        f.write(json.dumps(database)
    send_text_to_user(userid, "[b]Okay, your API key was succesfully stored.[/b]")

使用这种方法,我们甚至不需要在用户存在或不存在的情况下编写不同的保存,因为如果找到它就会删除它,因此当代码运行时它永远不存在而只需要保存每次都有“新”记录,除非API密钥已经属于另一个用户。

1 个答案:

答案 0 :(得分:2)

给定代码存在许多问题,所以让我们从头开始:

  1. 我们不需要创建空的dict对象来填充下一行

    data_to_save = {}
    data_to_save['savetime'] = str(datetime.datetime.now())[:19]
    data_to_save['api_key'] = key_submitted
    data_to_save['user'] = uniqueid
    

    当我们可以像

    那样创建它时
    data_to_save = {'savetime': str(datetime.datetime.now())[:19],
                    'api_key': key_submitted,
                    'user': uniqueid}
    
  2. if语句中不允许分配(docs处的更多内容)

    if api_exists = True:
    

    所以这一行会导致SyntaxError(我猜这是一个错字)。

  3. 检查

    if user_exists == True:
        ...
    

    are redundant,我们可以写

    if user_exists:
        ...
    

    并具有相同的效果。

  4. 在使用with语句时,我们不需要显式关闭文件,这是context managers:退出with语句块后的清理。

  5. 第一次迭代后的databases/api_key.txt文件将包含无效的JSON对象,因为您只是在文件末尾编写新的序列化data_to_save对象,而您应该修改database对象(似乎是字典列表)并编写了序列化的新版本,因此我们也不需要r+模式。

  6. 让我们定义实用程序功能,它可以保存新的API密钥数据,如

    def save_database(database,
                      api_keys_file_path="databases/api_keys.txt"):
        with open(api_keys_file_path, 'w') as api_keys_file:
            api_keys_file.write(json.dumps(database))
    

    然后我们可以有像

    这样的东西
    data_to_save = {'savetime': str(datetime.datetime.now())[:19],
                    'api_key': key_submitted,
                    'user': uniqueid}
    api_exists = False
    user_exists = False
    with open("databases/api_keys.txt", 'r') as api_keys_file:
        database = json.loads(api_keys_file.read())
        # database object should be iterable,
        # containing dictionaries as elements,
        # so only possible solution -- it is a list of dictionaries
        for i in database:
            if i['api_key'] == key_submitted:
                send_text_to_user(userid, "[b]Error: That API key is already in use.[/b]", "red")
                api_exists = True
            if i['user'] == uniqueid:
                user_exists = True
    
        if user_exists:
            if api_exists:
                send_text_to_user(userid, "[b]Error: Your API key was already saved at another time.[/b]", "red")
            else:
                # looking for user record in database
                user_record = next(record for record in database
                                   if record['user'] == uniqueid)
                # setting new API key
                user_record['api_key'] = key_submitted
                save_database(database)
                send_text_to_user(userid, "[b]Okay, I replaced your API key.[/b]", "green")
    
    if not user_exists:
        database.append(data_to_save)
        save_database(database)
    

    实施例

    我已创建目录databases,其中api_keys.txt文件包含单行

    []
    

    因为一开始我们没有API密钥。

    假设我们错过的对象被定义为

    key_submitted = '699aa2c2f9fc41f880d6ec79a9d55f29'
    uniqueid = 3
    userid = 42
    
    
    def send_text_to_user(userid, msg, color):
        print(msg)
    

    所以使用上面的代码,它给我第一个脚本执行空输出,并在第二个:

    [b]Error: That API key is already in use.[/b]
    [b]Error: Your API key was already saved at another time.[/b]
    

    进一步改进

    • 如果满足条件之一(API密钥或用户已在数据库中注册),我们break来自for是否应该循环?
    • 使用已编写的数据库而不是重新发明轮子会更好吗?如果您需要JSON个对象,请查看TinyDB