ablog

不器用で落着きのない技術者のメモ

AttributeError: 'str' object has no attribute 'read'

事象

Aurora PostgreSQL互換のアクティビティストリームを Kinesis Firehose で S3 に出力し、Lambda で読んで JSOn

  • コード
def load_iter(text: str) -> Generator:
    size = len(text)
    decoder = JSONDecoder()
    index = 0
    while index < size:
        obj, offset = decoder.raw_decode(text, index)
        yield obj
        search = WHITESPACE.search(text, offset)
        if search is None:
            break
        index = search.end()

(中略)

def lambda_handler(event, context):
    
(中略)

    s3r = boto3.resource('s3')
    s3c = boto3.client('s3')
    bucket = s3r.Bucket(s3_bucket_name)
    for obj in bucket.objects.filter(Prefix=s3_prefix):
        if not obj.key.endswith('/'):
            path = obj.key
            filename = os.path.basename(obj.key)
            local_path = '/tmp/' + filename
            s3r.Bucket(s3_bucket_name).download_file(path, local_path)

            text = open(local_path).read()
            for obj in load_iter(text):
                json_load = json.load(obj)
  • エラーメッセージ
AttributeError: 'str' object has no attribute 'read'

解決策

  • json.dumps で JSON 形式にエンコードする。
  • json.loads でデコードする。
  • json.dump、json.load はファイルを読む場合、json.dumps、json.loads は str、bytes、bytearray のいずれかのインスタンを読む場合に使う。例えば、上記のケースで json.load を使うと "AttributeError: 'str' object has no attribute 'read'" でエラーになる。
            for obj in load_iter(text):
                json_dumped = json.dumps(obj)
                json_load = json.loads(json_dumped)
                print(json_load)