![](/img/trans.png)
[英]How to Create list of filenames in an S3 directory using pyspark and/or databricks utils
[英]Get a list of files in S3 using PySpark in Databricks
我正在嘗試生成存儲桶/文件夾中所有 S3 文件的列表。 文件夾中通常有數百萬個文件。 我現在使用 boto,它每分鍾可以檢索大約 33k 個文件,即使是 100 萬個文件,也需要半小時。 我還將這些文件加載到數據框中,但生成並使用此列表作為跟蹤正在處理的文件的一種方式。
我注意到的是,當我要求 Spark 讀取文件夾中的所有文件時,它會列出自己的列表,並且能夠比 boto 調用更快地列出它們,然后處理這些文件。 我在 PySpark 中查找了一種方法來執行此操作,但沒有找到好的示例。 我得到的最接近的是一些 Java 和 Scala 代碼,用於列出使用 HDFS 庫的文件。
有沒有辦法在 Python 和 Spark 中做到這一點? 作為參考,我正在嘗試復制以下代碼片段:
def get_s3_files(source_directory, file_type="json"):
s3_resource = boto3.resource("s3")
file_prepend_path = f"/{'/'.join(source_directory.parts[1:4])}"
bucket_name = str(source_directory.parts[3])
prefix = "/".join(source_directory.parts[4:])
bucket = s3_resource.Bucket(bucket_name)
s3_source_files = []
for object in bucket.objects.filter(Prefix=prefix):
if object.key.endswith(f".{file_type}"):
s3_source_files.append(
(
f"{file_prepend_path}/{object.key}",
object.size,
str(source_directory),
str(datetime.now()),
)
)
return s3_source_files
這可以通過dbutils
非常簡單地實現。
def get_dir_content(ls_path):
dir_paths = dbutils.fs.ls(ls_path)
subdir_paths = [get_dir_content(p.path) for p in dir_paths if p.isDir() and p.path != ls_path]
flat_subdir_paths = [p for subdir in subdir_paths for p in subdir]
return list(map(lambda p: p.path, dir_paths)) + flat_subdir_paths
paths = get_dir_content('s3 location')
[print(p) for p in paths]
出於某種原因,使用 AWS CLI 命令大約比使用 boto 快 15 倍(!)。 不確定為什么會這樣,但這是我目前正在使用的代碼,以防有人發現它很方便。 基本上,使用s3api
列出對象,然后使用jq
操作輸出並將其變成我喜歡的形式。
def get_s3_files(source_directory, schema, file_type="json"):
file_prepend_path = f"/{'/'.join(source_directory.parts[1:4])}"
bucket = str(source_directory.parts[3])
prefix = "/".join(source_directory.parts[4:])
s3_list_cmd = f"aws s3api list-objects-v2 --bucket {bucket} --prefix {prefix} | jq -r '.Contents[] | select(.Key | endswith(\".{file_type}\")) | [\"{file_prepend_path}/\"+.Key, .Size, \"{source_directory}\", (now | strftime(\"%Y-%m-%d %H:%M:%S.%s\"))] | @csv'"
s3_list = subprocess.check_output(s3_list_cmd, shell=True, universal_newlines=True)
with open(f"s3_file_paths.csv", "w") as f:
f.truncate()
f.write(s3_list)
s3_source_files_df = spark.read.option("header", False).schema(schema).csv(f"s3_file_paths.csv")
return s3_source_files_df
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.