【问题标题】:Python script ran OK for weeks using cron job and it's now giving a KeyErrorPython 脚本使用 cron 作业运行了好几个星期,现在它给出了一个 KeyError
【发布时间】:2020-11-04 01:28:17
【问题描述】:

这是我要运行的代码。从 PyCharm 执行时工作。我设置了一个 cronjob,它在数周内都产生了奇迹。它现在给出了一个关键错误。由于我没有触及 cronjob 中的任何内容,因此找不到问题所在。

import csv
import json
import os
import random
import time
from urllib.parse import urlencode

import requests


API_URL = "https://community.koodomobile.com/widget/pointsLeaderboard?"
LEADERBOARD_FILE = "leaderboard_data.json"


def get_leaderboard(period: str = "allTime", max_results: int = 20) -> list:
    payload = {"period": period, "maxResults": max_results}
    return requests.get(f"{API_URL}{urlencode(payload)}").json()


def dump_leaderboard_data(leaderboard_data: dict) -> None:
    with open("leaderboard_data.json", "w") as jf:
        json.dump(leaderboard_data, jf, indent=4, sort_keys=True)


def read_leaderboard_data(data_file: str) -> dict:
    with open(data_file) as f:
        return json.load(f)


def parse_leaderboard(leaderboard: list) -> dict:
    return {
        item["name"]: {
            "id": item["id"],
            "score_data": {
                time.strftime("%Y-%m-%d %H:%M"): item["points"],
            },
            "rank": item["leaderboardPosition"],
        } for item in leaderboard
    }


def update_leaderboard_data(target: dict, new_data: dict) -> dict:
    for player, stats in new_data.items():
        target[player]["rank"] = stats["rank"]
        target[player]["score_data"].update(stats["score_data"])
    return target


def leaderboard_to_csv(leaderboard: dict) -> None:
    data_rows = [
        [player] + list(stats["score_data"].values()) 
        for player, stats in leaderboard.items()
    ]
    random_player = random.choice(list(leaderboard.keys()))
    dates = list(leaderboard[random_player]["score_data"])
    with open("the_data.csv", "w") as output:
        w = csv.writer(output)
        w.writerow([""] + dates)
        w.writerows(data_rows)


def script_runner():
    if os.path.isfile(LEADERBOARD_FILE):
        fresh_data = update_leaderboard_data(
            target=read_leaderboard_data(LEADERBOARD_FILE),
            new_data=parse_leaderboard(get_leaderboard()),
        )
        leaderboard_to_csv(fresh_data)
        dump_leaderboard_data(fresh_data)
    else:
        dump_leaderboard_data(parse_leaderboard(get_leaderboard()))


if __name__ == "__main__":
    script_runner()

这是它给我的错误。似乎字典有问题,因此出现 KeyError。

  File "/Users/Rob/PycharmProjects/Koodo/TEST.Json.py", line 75, in <module>
    script_runner()
  File "/Users/Rob/PycharmProjects/Koodo/TEST.Json.py", line 64, in script_runner
    fresh_data = update_leaderboard_data(
  File "/Users/Rob/PycharmProjects/Koodo/TEST.Json.py", line 44, in update_leaderboard_data
    target[player]["rank"] = stats["rank"]
KeyError: 'triggered123'

这是 JSON 文件中的数据:https://pastebin.com/HQyL4Kyx

【问题讨论】:

    标签: python macos web-scraping cron


    【解决方案1】:

    在我看来,您的代码第一次运行时,它会缓存排行榜。

    在随后的运行中,它将使用新值更新现有排行榜,方法是遍历每个新条目,找到它们的用户名,并在旧字典中查找该键。但是,如果有新用户,则旧字典中将不存在该键。

    您收到错误是因为玩家 triggered123 是排行榜的新用户,并且在您首次运行脚本后被列出。

    您需要更新update_leaderboard_data 来处理这种情况(通过在尝试访问之前检查该键是否存在于字典中)。

    【讨论】:

    • 我明白这就是问题所在。这就是我删除缓存中触发IS的json文件的原因。他现在就是这样。仅在运行 cronjob 时仍会发出此错误。 PyCharm 脚本有效。这就是为什么我感到困惑。 cron 是否将缓存保存在其他地方?编辑:我想我发现了这个问题。从 cron 选项卡运行时,该文件在其他地方创建。
    • 除非你改变它,否则你的工作目录就是你的 cronjobs 的主目录,所以/home/&lt;username&gt;/leaderboard_data.json(或简称~/leaderboard_data.json
    【解决方案2】:

    这是因为名为 triggered123 的键不在字典 target 中。

    来源:https://wiki.python.org/moin/KeyError

    问题在于,在update_leaderboard_data 中,您迭代新数据并使用它们在旧数据中查找。如果旧数据中不存在新密钥,您将获得KeyError

    尝试打印 dict target 以查看密钥 triggered123 是否在其中。

    或者使用带有默认值的dictget 方法:这样不会引发错误,您将能够在输出中搜索此默认值。

    【讨论】:

    • 当我打开 leaderboard_data.json 文件时,触发肯定是存在的。见编辑
    • triggeredtriggered123 ?
    • 触发123我说的是
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 2018-02-28
    • 2023-02-09
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多