TypeError:尽管调用了TypeError异常,但仍返回NoneType

2024-09-29 21:44:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在嵌套字典中搜索键和返回值。我用多个例外行设置了每个搜索,如下所示:

try:
    accounts_category = json_data['primaryTopic']['Accounts']['AccountCategory']
except (KeyError, TypeError) as e:
    accounts_category = ''

完成搜索后,我将按如下方式组合字符串和管道分隔符:

line = H + '|' + vn_id + '|' + sn_id + '|' + supplier_name + '\n'

然而,当我尝试组合变量时,我得到了一个TypeError。你知道吗

TypeError: coercing to Unicode: need string or buffer, NoneType found

如果我添加if语句,我的脚本就会工作:

try:
    accounts_next_due_date = json_data['primaryTopic']['Accounts']['NextDueDate']
    if accounts_next_due_date:
        pass
    else:
        accounts_next_due_date = 'e'
except (KeyError, TypeError) as e:
    accounts_next_due_date = 'e'

但这对我来说似乎是重复,我哪里做错了?你知道吗


Tags: idjsondatadateasnextduetry
3条回答

在Python 2中,尝试将unicode字符串与None连接会引发TypeError

>>> u'abcd' + None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: coercing to Unicode: need string or buffer, NoneType found

这就是问题所在。但根本原因是json_data可以有一个具有None值的键。下面是一个简化的示例:

>>> import json
>>> data = json.loads('{"a": 1, "b": null}')
{u'a': 1, u'b': None}
>>> b = data['b']
>>> b is None
True

这不会引发任何异常,因此None可以绑定到一个或多个用于构造line字符串的变量。您可以使用以下方法修复它:

accounts_category = json_data['primaryTopic']['Accounts']['AccountCategory']
if accounts_category is None:
    accounts_category = u''

您可以将其概括为一个函数,以便它可以应用于JSON数据中的其他键。你知道吗

此外,还可以使用str.join()更好地执行字符串的串联:

line = u'|'.join((H, vn_id, sn_id, supplier_name)

我听到你说的是你执行这个代码:

try:
    accounts_category = json_data['primaryTopic']['Accounts']['AccountCategory']
except (KeyError, TypeError) as e:
    accounts_category = ''

后来的accounts_category(或者其他一些用这种方式处理的变量)是None,而不是''。你知道吗

显然,发生这种情况是因为没有出现错误。相反,json_data['primaryTopic']['Accounts']['AccountCategory'](或者其他什么)实际上是None(也就是说,在原始JSON中是null)。你知道吗

避免这种情况的最简单方法是使用or关键字添加一个默认值(如果值为“false ish”),如下所示:

accounts_category = json_data['primaryTopic']['Accounts']['AccountCategory'] or ''

也可以在使用值时执行此操作:

line = "%s|%s|%s|%s\n" % (H, vn_id, sn_id, supplier_name or '')

作为奖励,因为这看起来并不是真正引起错误,所以您可能能够摆脱所有try/except样板文件。如果你还需要做很多次的爱的话,那就去做吧!例如:

def jsonfield(jsonobj, default, *names):
    try:
        for name in names:
             jsonobj = jsonobj[name]
        return jsonobj or default
    except (TypeError, KeyError):
        return default

accounts_category = json_field(json_data, "", "primaryTopic", "Accounts", "AccountCategory")
accounts_next_due_date = None

try:
    accounts_next_due_date = json_data['primaryTopic']['Accounts']['NextDueDate']
except (KeyError, TypeError):
    pass # or log the error
finally:
    if not accounts_next_due_date:
        accounts_next_due_date = "e"

相关问题 更多 >

    热门问题