Python将.json文件从GCS并行读取到DF中
TL;DR:Python将.json文件从GCS并行读取到DF中,python,pandas,parallel-processing,google-cloud-storage,python-asyncio,Python,Pandas,Parallel Processing,Google Cloud Storage,Python Asyncio,TL;DR:asynciovsmulti-processingvsthreadingvs 我想创建一个并行python函数,该函数从GCS目录中读取数十万个小型.json文件,然后将这些.json转换为pandas数据帧,然后将pandas数据帧写入BigQuery表 以下是函数的非并行版本: import gcsfs import pandas as pd from my.helpers import get_gcs_file_list def load_gcs_to_bq(gcs_direc
asyncio
vsmulti-processing
vsthreading
vs
我想创建一个并行python函数,该函数从GCS目录中读取数十万个小型.json文件,然后将这些.json转换为pandas数据帧,然后将pandas数据帧写入BigQuery表
以下是函数的非并行版本:
import gcsfs
import pandas as pd
from my.helpers import get_gcs_file_list
def load_gcs_to_bq(gcs_directory, bq_table):
# my own function to get list of filenames from GCS directory
files = get_gcs_file_list(directory=gcs_directory) #
# Create new table
output_df = pd.DataFrame()
fs = gcsfs.GCSFileSystem() # Google Cloud Storage (GCS) File System (FS)
counter = 0
for file in files:
# read files from GCS
with fs.open(file, 'r') as f:
gcs_data = json.loads(f.read())
data = [gcs_data] if isinstance(gcs_data, dict) else gcs_data
this_df = pd.DataFrame(data)
output_df = output_df.append(this_df)
# Write to BigQuery for every 5K rows of data
counter += 1
if (counter % 5000 == 0):
pd.DataFrame.to_gbq(output_df, bq_table, project_id=my_id, if_exists='append')
output_df = pd.DataFrame() # and reset the dataframe
# Write remaining rows to BigQuery
pd.DataFrame.to_gbq(output_df, bq_table, project_id=my_id, if_exists='append')
此函数非常简单:
- 抓取
,gcs中的文件名列表['gcs_dir/file1.json','gcs_dir/file2.json',…]
- 在每个文件名上循环,然后:
- 从GCS读取文件
- 将数据转换为数据类型
- 附加到主目录的
- 每5K循环一次,写入BigQuery(因为随着DF变大,追加的速度会变慢)
编辑:下面的解决方案很有帮助,但我对从python脚本中并行运行特别感兴趣。Pandas正在处理一些数据清理,使用
bq load
将抛出错误。这和这两个任务对于这个任务可能是有用的,可能是比线程处理或多重处理更好的选择…,而不是将并行处理添加到Python代码中,而是考虑并行调用多个Python程序。这是一个技巧,它使在命令行上获取文件列表的程序更容易使用。因此,为了这个帖子,让我们考虑改变你的程序中的一行:
您的线路:
# my own function to get list of filenames from GCS directory
files = get_gcs_file_list(directory=gcs_directory) #
新行:
files = sys.argv[1:] # ok, import sys, too
现在,您可以通过以下方式调用程序:
PROCESSES=100
get_gcs_file_list.py | xargs -P $PROCESSES your_program
xargs
现在将获取由get_gcs_file_list.py
输出的文件名,并并行调用您的_程序
多达100次,在每一行上匹配尽可能多的文件名。我相信文件名的数量限制在shell允许的最大命令大小之内。如果100个进程不足以处理您的所有文件,xargs将再次(一次又一次)调用您的_程序,直到它从stdin读取的所有文件名都得到处理xargs
确保同时运行的\u程序调用不超过100次。您可以根据主机可用的资源更改进程数。您可以直接使用bq
命令来代替此操作
bq命令行工具是用于BigQuery的基于Python的命令行工具
当您使用这个命令时,加载在google的网络中进行,这比我们创建数据帧并加载到表中要快得多
bq load \
--autodetect \
--source_format=NEWLINE_DELIMITED_JSON \
mydataset.mytable \
gs://mybucket/my_json_folder/*.json
有关详细信息-您为什么要这样做?您可以直接使用bq
命令在bigquery中提供GCS文件夹的路径和表名。这将是快速的bq
命令你指的是什么?我已经给出了一个答案,让其他面临同样问题的人可以看看这个好主意。谢谢分享。目前,我在每天运行的AirflowDAG
中以tasks
的形式调用我的程序,我不太确定如何将此模式引入Airflow。我将尝试此方法。我担心我的数据会出现类型
问题,这可能是因为数据混乱,尽管您的共享命令似乎有一个--autodetect
标志来处理这个问题?--autodetect
将自动检测类型并尝试应用类型,否则它将抛出错误