元々EC2環境でcronを設定して使っていたPythonコードをLambdaに引っ越していたときのこと。
リソースを作成してコードもデプロイして、いざLambdaを実行してみると下記のような内容でエラーになりました。
[ERROR] TypeError: main() takes 0 positional arguments but 2 were given
Traceback (most recent call last):
File "/var/runtime/awslambdaric/bootstrap.py", line 177, in handle_event_request
response = request_handler(event, lambda_context)
「main関数は引数取らないみたいだけど、2つ渡されてるよ!」とのこと。
実際のmain関数はこんな感じ。
def main():
# 取得期間(end_dayは含まない)
start_day, end_day = get_term()
raw_data = get_cost_and_usage(start_day, end_day)
if RAW_DEBUG == True:
print(raw_data)
print("-------------------------------------------------")
refill_data = refill(raw_data)
message = round_cost(refill_data)
〜中身は特に関係ないので以下略〜
で、これを実行するPythonFunctionをCDKで作成していました。
propsからすべての値を渡しているのでなんのこっちゃ感はありますが、特別なことはしていません。
const func = new PythonFunction(this, props.lambdaConfig.functionName, {
functionName: props.lambdaConfig.functionName,
runtime: Runtime.PYTHON_3_13,
entry: props.lambdaConfig.entry,
index: props.lambdaConfig.index,
handler: props.lambdaConfig.handler,
timeout: Duration.minutes(3),
vpc: Vpc.fromVpcAttributes( this, `${projectName}-lambda-vpc`, {
availabilityZones: props.vpcConfig.availabilityZones,
vpcId: props.vpcConfig.vpcId,
}),
vpcSubnets: {
subnets: props.vpcConfig.privateSubnetIds.map((subnet) =>
Subnet.fromSubnetId(this, `${subnet}`, subnet)
),
},
role: Role.fromRoleArn(this, 'lambda-execution-role', props.roleArn),
logGroup: LogGroup.fromLogGroupName(this, props.lambdaConfig.logGroupName, props.lambdaConfig.logGroupName),
});
別に実行時になにも引数渡すとかやってないけどなぁ?身に覚えないんですけどー!と思っていましたが
Lambdaは実行時に イベントオブジェクト と コンテキストオブジェクト を渡してくるそうで、これを受け取れるようにしてやる必要がありました。初学者向けチュートリアルにも書かれていました…🐣
イベントオブジェクトは、AWSサービスから呼び出された際にその呼び出し元の情報が詰まっているオブジェクト。例えばS3から関数が呼び出された場合はバケット名や、オブジェクト名等が入っていたりします。これを使って、トリガーとなったS3オブジェクトを編集する…みたいな実装を書けたりするわけですね。
コンテキストオブジェクトは、関数の呼び出しと実行環境に関する情報が詰まっているオブジェクト。メモリサイズやリクエストIDなどが含まれており、関数のモニタリングなんかに使えたりします。
ということで言われるがままにmain関数を修正してやると無事実行できました👏
def main(event, lambda_context):
# 取得期間(end_dayは含まない)
start_day, end_day = get_term()
raw_data = get_cost_and_usage(start_day, end_day)
if RAW_DEBUG == True:
print(raw_data)
print("-------------------------------------------------")
refill_data = refill(raw_data)
message = round_cost(refill_data)
〜中身は特に関係ないので以下略〜