正在将格式错误的gzipped S3对象复制到RDS或有效地更改行终止符



我有一个来自第三方数据提供商的S3对象,该数据提供商(通过任何机制(不一致地编写了这个对象。标题行由换行n终止,但随后的每一行由回车+换行rn终止。此对象是gzipped csv。我想从他们的S3 bucket中复制这个对象,然后使用aws_s3扩展将该对象复制到PostgreSQL RDS表中。这些扩展通常可以处理gzipped的csv文件,但由于标题行与其余行具有不同的行终止符,即使使用复制选项'(format csv, delimiter '','', header true)':,复制也会失败,并出现以下错误

psycopg2.errors.BadCopyFileFormat: unquoted carriage return found in data
HINT:  Use quoted CSV field to represent carriage return.

最终,我从PostgreSQL源代码中了解到,这是因为行终止符不一致;PostgreSQL引擎即使使用CCD_ 5也会查找第一行以确定行终止符。

所以我的第一个问题是,我在这里的评估是真的吗,或者有没有一种方法可以指示PostgreSQL COPY处理一个csv文件,其中头在末尾有一个换行符,但在所有其他行结束时有一个回车符?

假设它不能,那么在将这个对象写入S3之前,我现在需要规范化行终止符。从boto3get_object,我有一堆字节:

resp = s3_client.get_object(Bucket="the-source-bucket", Key="location/of/the_object.csv.gz")
body_bytes = resp["Body"].read()

在做类似的事情之前,我想用n替换rn的任何实例

s3_client.put_object(
Bucket="the-destination-bucket", 
Key="/location/of/the/output.csv[.gz?]", 
Body=<body_bytes with the correct line terminator everywhere>
)

最有效的方法是什么?

正如评论中所指出的,RDS无法处理不一致的行终止符,所以我必须事先对它们进行规范化。我最终做了这样的事情:

resp = s3_client.get_object(
Bucket="the-source-bucket",
Key="location/of/the_object.csv.gz")
)
body = resp["Body"].read()
# This line splits on any line terminator,
# whether or not it is consistent between lines
lines = gzip.decompress(body).splitlines()
s3_client.put_object(
ContentEncoding="gzip",
# Now we write the object with a consistent line terminator
Body=gzip.compress(b"n".join(lines)),
Bucket="the-destination-bucket",
Key="location/of/the_object.csv.gz"
)

最新更新