从Google Cloud Storage中的csv中读取n行以与Python csv模块一起使用

时间:2019-07-09 19:48:38

标签: python-3.x csv google-cloud-platform google-cloud-storage

我有各种非常大的csv文件(每个大小约4GB),它们包含不同的格式。这些来自十多个不同制造商的数据记录器。我正在尝试将所有这些整合到BigQuery中。为了每天加载这些文件,我想先将这些文件加载​​到Cloud Storage中,确定架构,然后再加载到BigQuery中。由于某些文件具有其他标题信息(从2到〜30行),因此我产生了自己的函数,可以从每个文件的样本(约100行)中确定最可能的标题行和模式,然后,我可以在将文件加载到BQ时在job_config中使用。

当我使用从本地存储直接到BQ的文件时,这可以很好地工作,因为我可以使用上下文管理器,然后使用Python的csv模块,尤其是嗅探器和阅读器对象。但是,似乎没有等效的方法可以直接从Storage使用上下文管理器。我不想绕过Cloud Storage,以防在加载到BQ中时这些文件中的任何一个被中断。

我可以开始工作的地方:

# initialise variables
with open(csv_file, newline  = '', encoding=encoding) as datafile:
    dialect = csv.Sniffer().sniff(datafile.read(chunk_size))
    reader = csv.reader(datafile, dialect)
    sample_rows = []
    row_num  = 0
    for row in reader:
         sample_rows.append(row)
         row_num+=1
         if (row_num >100):
             break
    sample_rows
# Carry out schema  and header investigation...

在Google Cloud Storage中,我尝试使用download_as_string和download_to_file,它们提供数据的二进制对象表示形式,但后来我无法使csv模块与任何数据一起使用。我尝试使用.decode('utf-8'),它返回带有\ r \ n的looong字符串。然后,我使用splitlines()来获取数据列表,但是csv函数仍继续提供一种方言和阅读器,该方言和阅读器将数据作为每个条目分成单个字符。

是否有人设法解决了将csv模块与Cloud Storage中存储的文件一起使用的问题,而无需下载整个文件?

1 个答案:

答案 0 :(得分:1)

在GitHub上查看csv源代码后,我设法使用Python中的io模块和csv模块来解决此问题。 io.BytesIO和TextIOWrapper是要使用的两个关键功能。可能不是常见的用例,但我想在这里发布答案,以节省一些需要它的时间。

# Set up storage client and create a blob object from csv file that you are trying to read from GCS.
content = blob.download_as_string(start = 0, end = 10240) # Read a chunk of bytes that will include all header data and the recorded data itself.
bytes_buffer = io.BytesIO(content)
wrapped_text = io.TextIOWrapper(bytes_buffer, encoding = encoding, newline =  newline)
dialect = csv.Sniffer().sniff(wrapped_text.read()) 
wrapped_text.seek(0)
reader = csv.reader(wrapped_text, dialect)
# Do what you will with the reader object