質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.53%
AWS Lambda

AWS Lambdaは、クラウド上でアプリを実行できるコンピューティングサービス。サーバーのプロビジョニングや管理を要せず複数のイベントに対してコードを実行します。カスタムロジック用いた他AWSサービスの拡張やAWSの規模やパフォーマンスを用いたバックエンドサービスを作成できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Amazon S3

Amazon S3 (Simple Storage Service)とはアマゾン・ウェブ・サービスが提供するオンラインストレージサービスです。

Q&A

解決済

1回答

1190閲覧

Pythonストリームでcsvを読み込みdatetime型変換し転送する際Object of type datetime is not JSON serializableエラーが発生する

msy47

総合スコア26

AWS Lambda

AWS Lambdaは、クラウド上でアプリを実行できるコンピューティングサービス。サーバーのプロビジョニングや管理を要せず複数のイベントに対してコードを実行します。カスタムロジック用いた他AWSサービスの拡張やAWSの規模やパフォーマンスを用いたバックエンドサービスを作成できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Amazon S3

Amazon S3 (Simple Storage Service)とはアマゾン・ウェブ・サービスが提供するオンラインストレージサービスです。

0グッド

0クリップ

投稿2023/01/11 14:17

編集2023/01/12 12:11

前提

S3にアップロードされたcsvを
ストリームで読み込み、型変換してOpensearchへ転送する。
その際、一部の型をintやdatetimeへ変換して転送する必要がある。

問題
datetime変換エラーとなり転送できない

実現したいこと

  • ストリームで読み込ん任意の項目をdatetime型に変換したい

取り込むcsv
ヘッダ8個,データ8個

vmanage_host, systemip, hostname , devicemodel, bfdSessionsUp, bfdSessions, dt, IPsecTunnel vmanageABC, 123.456.789.012, vedgeABC, deviceABC, 99, 999, 2022/1/1 01:01, 123

発生している問題・エラーメッセージ

datetime変換エラーとなり転送できない

[ERROR] TypeError : Object of type datetime is not JSON serializable

該当のソースコード

Python(Lambda)

1 2import boto3 3import re 4import requests 5import csv 6import io 7from datetime import datetime 8from requests_aws4auth import AWS4Auth 9 10#配列(不要指摘→後に削除) 11#vmanage_host = [] 12#systemip = [] 13#hostname = [] 14#devicemodel = [] 15#bfdSessionsUp = [] 16#bfdSessions = [] 17#datetime = [] 18#IPsecTunnel = [] 19 20 21region = '(略)' # e.g. us-west-1 22service = 'es' 23credentials = boto3.Session().get_credentials() 24awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token) 25 26host = '(略)' # the OpenSearch Service domain, e.g. https://search-mydomain.us-west-1.es.amazonaws.com 27index = 'lambda-s3-index_test' 28type = '_doc' 29url = host + '/' + index + '/' + type 30 31headers = { "Content-Type": "application/json" } 32 33s3 = boto3.client('s3') 34 35# Lambda execution starts here 36def handler(event, context): 37 for record in event['Records']: 38 39 # Get the bucket name and key for the new file 40 bucket = record['s3']['bucket']['name'] 41 key = record['s3']['object']['key'] 42 43 # Get, read, and split the file into lines 44 obj = s3.get_object(Bucket=bucket, Key=key) 45 body = obj['Body'].read() 46 textIo = io.TextIOWrapper(io.BytesIO(body)) 47 48 skiptext = next(textIo) 49 50 # Match the regular expressions to each line and index the JSON 51 for row in csv.reader(textIo): 52 53 print(row) 54 vmanage_host = row[0] 55 systemip = row[1] 56 hostname = row[2] 57 devicemodel = row[3] 58 bfdSessionsUp = row[4] 59 bfdSessions = row[5] 60 infgettime = row[6] 61 IPsecTunnel = row[7] 62 63 print(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7]) 64 65 document = { 66 "vmanage_host ": vmanage_host , 67 "systemip ": systemip , 68 "hostname ": hostname , 69 "devicemodel ": devicemodel , 70 "bfdSessionsUp": [int(bfdSessionsUp)], 71 "bfdSessions ": [int(bfdSessions)], 72 "infgettime ": [datetime.strptime(infgettime , `%Y/%m/%d %H:%M`)], 73 "IPsecTunnel ": [int(IPsecTunnel)], 74 } 75 r = requests.post(url, auth=awsauth, json=document, headers=headers)

試したこと

【Python】日付時刻・文字列・数値型データの相互変換方法|datetime・dateモジュールの基本操作入門
https://di-acc2.com/programming/python/22894/#index_id1

を参考に修正したが、いずれも事象解消には至らず。

補足情報(FW/ツールのバージョンなど)

Python3.9

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melian

2023/01/11 18:49

最初に、 vmanageABC, 123.456.789.012, vedgeABC, deviceABC, 1, 2, 3, 2022/1/1 01:01, 123 の行は 9 個の要素がありますが、ヘッダには 8 個のカラムしかありません。 それから datetime というクラス名がバッティングしています。 from datetime import datetime datetime = [] # コードの先頭部分 datetime = row[6] # for loop 内 for loop 内で使っている datetime(変数名)を変更する必要があります。また、「# 配列」というコメント以降の初期化部分は不要でしょう。
msy47

2023/01/12 00:28

melianさん ご指摘ありがとうございます。 以下修正いたしました >vmanageABC, 123.456.789.012, vedgeABC, deviceABC, 1, 2, 3, 2022/1/1 01:01, 123 >の行は 9 個の要素がありますが、ヘッダには 8 個のカラムしかありません。 要素は8,ヘッダも8になります。 >from datetime import datetime > >datetime = [] # コードの先頭部分 >datetime = row[6] # for loop 内 > >for loop 内で使っている datetime(変数名)を変更する必要があります。また、「# 配列」というコメント以降の初期化部分は不要でしょう。 変数名を変更しました。 datetime を infgettime へ変更
can110

2023/01/12 01:00

「for row in lines csv.reader(textIo):」行や 「"infgettime ": [datetime.strftime(infgettime , `%Y/%m/%d %H:%M`)]」行などで 構文エラーになるようです。実際のコードと相違はないでしょうか。 さらに上記コードが正しいとしても infgettime変数はstr型のはずなのでdatetime.strftimeでTypeErrorが発生するはずです。
msy47

2023/01/12 01:08

melianさん ご指摘ありがとうございます。 転記ミス申し訳ありません。 >「for row in lines csv.reader(textIo):」行 以下修正いたしました for row in csv.reader(textIo): >"infgettime ": [datetime.strftime(infgettime , `%Y/%m/%d %H:%M`)] 以下修正いたしました "infgettime ": [datetime.strptime(infgettime , `%Y/%m/%d %H:%M`)]
melian

2023/01/12 01:14

そうなりますと、簡単な対応方法としては json.dumps に default のコンバータを指定することかと思います。以下の様にすると、datetime 型インスタンスを文字列に変換してから requests.post() に渡します。 r = requests.post(url, auth=awsauth, data=json.dumps(document, default=str), headers=headers)
guest

回答1

0

ベストアンサー

datetime.strptimeの戻り値datetime型はデフォルトではJSON(文字列)化できないので提示エラーが発生しています。
とりあえずstr(datetime.strptime(infgettime , ~))のように明示的に文字列化してやればよいです。

投稿2023/01/12 01:27

can110

総合スコア38230

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

msy47

2023/01/12 03:11

丁寧迅速な指摘・回答ありがとうございます! >JSON(文字列)化できないので提示エラーが発生しています。 こちらについては、Opensearch側か、転送側のロジックで対応するか検討します。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.53%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問