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

Why is this throwing a KeyError when it has a value?

我已经逐步完成并使用 pdb trace 检查了每个值,但无法弄清楚为什么我会收到 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'

没有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')