当我在Zapier中使用这段代码时,为什么会出现Runtime.MarshalError错误?

8
以下代码给我报错:
运行时.MarshalError: 无法编组响应:{'Yes'}不可JSON序列化。
from calendar import monthrange

def time_remaining_less_than_fourteen(year, month, day):
    a_year = int(input['year'])
    b_month = int(input['month'])
    c_day = int(input['day'])
    days_in_month = monthrange(int(a_year), int(b_month))[1]
    time_remaining = ""

    if (days_in_month - c_day) < 14:
        time_remaining = "No"
        return time_remaining

    else:
        time_remaining = "Yes"
        return time_remaining


output = {time_remaining_less_than_fourteen((input['year']), (input['month']), (input['day']))}

#print(output)

当我移除 {...} 后,它会抛出错误:'unicode' 对象没有 'copy' 属性。
2个回答

27

我在使用Kinesis Firehose的lambda转换蓝图kinesis-firehose-process-record-python时遇到了这个问题,导致我来到了这里。因此,我将为任何遇到类似问题的人发布一个解决方案。

该蓝图是:

from __future__ import print_function

import base64

print('Loading function')


def lambda_handler(event, context):
    output = []

    for record in event['records']:
        print(record['recordId'])
        payload = base64.b64decode(record['data'])

        # Do custom processing on the payload here

        output_record = {
            'recordId': record['recordId'],
            'result': 'Ok',
            'data': base64.b64encode(payload)
        }
        output.append(output_record)

    print('Successfully processed {} records.'.format(len(event['records'])))

    return {'records': output}

需要注意的是,AWS提供的用于Python的Firehose lambda蓝图适用于Python 2.7,并且它们与Python 3不兼容。原因是在Python 3中,字符串和字节数组是不同的。

使其适用于由Python 3.x运行时支持的lambda的关键更改是:

更改

'data': base64.b64encode(payload)

进入

'data': base64.b64encode(payload).decode("utf-8")
否则,由于无法序列化使用base64.b64encode返回的字节数组的JSON,lambda出现了错误。

2
谢谢Marcin,我也遇到了完全相同的问题,你的答案让我省去了很多麻烦。Python 2.7蓝图让我认为Kinesis期望记录数据是bytes类型。转换为str甚至没有在我的脑海中出现。快速建议:base64.b64encode(payload).decode("utf-8")可以简单地写成base64.b64encode(payload).decode()。Base64数据本身就是ASCII码。ASCII本身就是UTF-8,在Python 3中,编码参数的默认值就是UTF-8。在那里指定编解码器只是多余的。 - Rafa Viotti
2
@Rafa 很高兴我的回答有所帮助,也感谢你的好建议。 - Marcin
2
不确定你是在字面上还是比喻上拯救了我的生命,但无论如何,感谢你的回答。^^ +1 - Flo
1
感谢您节省了我的时间,@Marcin。我遇到了同样的问题,您的解决方案起作用了。 - VinayBS

3

大家好,我是 Zapier 平台团队的 David。

根据文档

output:一个字典或字典列表,将作为此代码的“返回值”。如果您愿意,可以明确提前返回。 这必须是可JSON序列化的!

在您的情况下,output 是一个集合:

>>> output = {'Yes'}
>>> type(output)
<class 'set'>
>>> json.dumps(output)
Object of type set is not JSON serializable

为了使其可序列化,您需要一个具有键和值的字典。将您的最后一行更改为包含一个键,它将按您的预期工作:
#         \ here /
output = {'result': time_remaining_less_than_fourteen((input['year']), (input['month']), (input['day']))}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接