【问题标题】:Error handling in Python with JSON and a dictionary使用 JSON 和字典在 Python 中处理错误
【发布时间】:2013-02-07 04:35:15
【问题描述】:

我目前有一个 Python 2.7 脚本,它可以抓取 Facebook 并从每个页面捕获一些 JSON 数据。 JSON 数据包含个人信息。 JSON数据示例如下:-

{
   "id": "4",
   "name": "Mark Zuckerberg",
   "first_name": "Mark",
   "last_name": "Zuckerberg",
   "link": "http://www.facebook.com/zuck",
   "username": "zuck",
   "gender": "male",
   "locale": "en_US"
}

JSON 值可能因页面而异。上面的示例列出了所有可能的值,但有时,“用户名”之类的值可能不存在,我可能会遇到 JSON 数据,例如:-

{
   "id": "6",
   "name": "Billy Smith",
   "first_name": "Billy",
   "last_name": "Smith",
   "gender": "male",
   "locale": "en_US"
}

有了这些数据,我想填充一个数据库表。因此,我的代码如下:-

results_json = simplejson.loads(scraperwiki.scrape(profile_url))
        for result in results_json:
            profile = dict()
            try:
                profile['id'] = int(results_json['id'])
            except:
                profile['id'] = ""
            try:
                profile['name'] = results_json['name']
            except:
                profile['name'] = ""
            try:
                profile['first_name'] = results_json['first_name']
            except:
                profile['first_name'] = ""
            try:
                profile['last_name'] = results_json['last_name']
            except:
                profile['last_name'] = ""
            try:
                profile['link'] = results_json['link']
            except:
                profile['link'] = ""
            try:
                profile['username'] = results_json['username']
            except:
                profile['username'] = ""
            try:
                profile['gender'] = results_json['gender']
            except:
                profile['gender'] = ""
            try:
                profile['locale'] = results_json['locale']
            except:
                profile['locale'] = ""

我有这么多尝试/例外的原因是考虑到网页上不存在键值的情况。尽管如此,这似乎是处理这个问题的一种非常笨拙和混乱的方式。

如果我删除这些 try / exception 子句,如果我的爬虫遇到缺少的键,它会返回一个 KeyError,例如 "KeyError: 'username'",并且我的脚本停止运行。

有关处理这些错误的更智能和改进方法的任何建议,以便在遇到丢失密钥时,脚本继续。

我已尝试创建 JSON 值列表并希望使用 IF 子句遍历它们,但我就是想不通。

【问题讨论】:

    标签: python json dictionary python-2.7


    【解决方案1】:

    请改用.get() method

    >>> a = {'bar': 'eggs'}
    >>> a['foo']
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyError: 'foo'
    >>> a.get('foo', 'default value')
    'default value'
    >>> a.get('bar', 'default value')
    'eggs'
    

    .get() 方法返回请求键的值,如果键缺失,则返回默认值。

    或者您可以为每个键创建一个带有空字符串的新字典,并在其上使用.update()

    profile = dict.fromkeys('id name first_name last_name link username gender locale'.split(), '')
    profile.update(result)
    

    dict.fromkeys() 创建一个字典,将您请求的所有键设置为给定的默认值(上例中的''),然后我们使用.update() 复制result 字典中的所有键和值,替换任何已经存在的东西。

    【讨论】:

    • 遗憾的是,尽管我很喜欢 fromkeys/update 解决方案,但我认为它不适用于 OP 的情况。至少其中一个值必须用int 进行转换,并且JSON 对象可能具有他不想复制到profile 中的额外键。但是您也给出的get 答案显然没有任何此类问题,并且对于 OP 来说已经足以使他的代码具有 4 倍的可读性和可维护性,这是一个相当大的胜利。
    • @abarnert:.fromkeys()/.update() 设置工作正常,因为 source JSON 中也没有使用 int。除非明确说明,否则不要假设 id 将被视为 int。 :-) 如果键太多,很容易为更新编写生成器表达式(.update() 接受元组和字典)。
    • 在 OP 的代码中,他有 profile['id'] = int(results_json['id'])。因此,据推测,JSON 将 int 呈现为字符串,但 profile 必须具有实际整数。
    • @MartijnPieters。完美 - 您的解决方案如我所愿,它使我的成本降低了 50%。谢谢
    • @abarnert:嗯,不知道我是怎么错过的。 :) 不过,添加profile['id'] = int(profile['id']) 并不难。 :-P
    猜你喜欢
    • 2016-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-28
    • 2014-08-12
    • 2019-08-26
    • 1970-01-01
    相关资源
    最近更新 更多