为什么在它有值时抛出KeyError?

时间:2016-02-26 23:25:19

标签: python string-formatting keyerror

我已逐步完成此操作并使用pdb跟踪检查每个值,但无法弄清楚为什么我得到了KeyError,所有内容都有其预期值。这是功能:

def get_formatted_timestamp(date_field, time_field):
    # expects date_field = yyyy-M-d
    # expects time_field = H:m:s
    # outputs yyyy-MM-ddTHH:mm:ss:SSSZ ('T' and 'Z' are literals)
    dt = date_field.strip().split('/')
    tm = time_field.strip().split(':')
    if len(dt) != 3 or len(tm) != 3 or len(dt[0]) != 4:
        print 'invalid date or time: {} {}'.format(date_field, time_field)
        return '1900-01-01T00:00:00.000Z'  # error date value
    y = dt[0]
    M = dt[1] if len(dt[1]) == 2 else '0'+dt[1]
    d = dt[2] if len(dt[2]) == 2 else '0'+dt[2]
    H = tm[0] if len(tm[0]) == 2 else '0'+tm[0]
    m = tm[1] if len(tm[1]) == 2 else '0'+tm[1]
    s = tm[2] if len(tm[2]) == 2 else '0'+tm[2]
    return '{y}-{M}-{d}T{H}:{m}:{s}.000Z'.format(y, M, d, H, m, s)  # KeyError

错误是:

KeyError: 'y'

但是,y具有正确的年份字符串值(我检查repr(y);它是预期的字符串)。我还检查了dt[0]是否有效,并且显示了正确的年份值。

当所有内容都具有预期值时,为什么会抛出KeyError?我很难过。

这是pdb输出,我手动检查了每个值:

(Pdb) print repr(dt[0])
'2014'
(Pdb) print repr(y)
'2014'
(Pdb) print repr(M)
'02'
(Pdb) print repr(d)
'10'
(Pdb) print repr(H)
'15'
(Pdb) print repr(m)
'35'
(Pdb) print repr(s)
'19'

1 个答案:

答案 0 :(得分:5)

您不会拥有密钥y,因为您没有任何关键字参数。您只有位置参数。那不是一回事;即使您使用具有该名称的变量也不意味着它也是关键字参数。

使用数字来提取位置参数,或使用实际的关键字参数。如果所有局部变量都与插槽名称匹配,则可以使用locals()提供这些关键字参数:

return '{y}-{M}-{d}T{H}:{m}:{s}.000Z'.format(**locals())

但除此之外,您必须为格式中使用的每个名称添加一个实际的关键字:

return '{y}-{M}-{d}T{H}:{m}:{s}.000Z'.format(y=y, M=M, d=d, H=H, m=m, s=s)

请注意,您的代码似乎重新发明了日期解析和日期格式化轮。以下内容可以做同样的事情,但也验证您有一个有效的日期(例如,在闰年之外没有2月29日等):

from datetime import datetime

def get_formatted_timestamp(date_field, time_field):
    # expects date_field = yyyy-M-d
    # expects time_field = H:m:s
    # outputs yyyy-MM-ddTHH:mm:ss.000Z ('T' and 'Z' are literals)
    try:
        dt = datetime.strptime('{} {}'.format(date_field, time_field), '%Y-%m-%d %H:%M:%S')
    except ValueError:
        return '1900-01-01T00:00:00.000Z'  # error date value
    return dt.strftime('%Y-%m-%dT%H:%M:%S.000Z')