簡體   English   中英

如何使用 PySpark 計算 ADLS 中的目錄大小?

[英]How to calculate a Directory size in ADLS using PySpark?

我想計算一個包含子文件夾和子文件的目錄(例如- XYZ)大小。 我想要 XYZ 中所有文件和所有內容的總大小。

我可以找出特定路徑內的所有文件夾。 但我想要所有的大小。 我也看到了

display(dbutils.fs.ls("/mnt/datalake/.../XYZ/.../abc.parquet"))

給我 abc 文件的數據大小。 但我想要 XYZ 的完整大小。

dbutils.fs.ls沒有像cpmvrm這樣的遞歸功能。 因此,您需要自己迭代。 這是一個將為您完成任務的片段。 從 Databricks Notebook 運行代碼。

from dbutils import FileInfo
from typing import List

root_path = "/mnt/datalake/.../XYZ"

def discover_size(path: str, verbose: bool = True):
  def loop_path(paths: List[FileInfo], accum_size: float):
    if not paths:
      return accum_size
    else:
      head, tail = paths[0], paths[1:]
      if head.size > 0:
        if verbose:
          print(f"{head.path}: {head.size / 1e6} MB")
        accum_size += head.size / 1e6
        return loop_path(tail, accum_size)
      else:
        extended_tail = dbutils.fs.ls(head.path) + tail
        return loop_path(extended_tail, accum_size)

  return loop_path(dbutils.fs.ls(path), 0.0)

discover_size(root_path, verbose=True)  # Total size in megabytes at the end

如果該位置安裝在 dbfs. 然后你可以使用du -h方法(沒有測試它)。 如果您在筆記本中,請創建一個新單元格:

%sh
du -h /mnt/datalake/.../XYZ

嘗試使用 dbutils ls 命令,獲取 dataframe 中的文件列表,並在 size 列上使用聚合 function SUM() 進行查詢:

val fsds = dbutils.fs.ls("/mnt/datalake/.../XYZ/.../abc.parquet").toDF

fsds.createOrReplaceTempView("filesList")

display(spark.sql("select COUNT(name) as NoOfRows, SUM(size) as sizeInBytes from fileListPROD"))

@Emer 的答案很好,但可能會遇到RecursionError: maximum recursion depth exceeded非常快,因為它對每個文件進行遞歸(如果你有 X 個文件,你將有 X 個復疊遞歸)。

這與僅針對文件夾的遞歸相同:

%python
from dbutils import FileInfo
from typing import List

def discover_size2(path: str, verbose: bool = True):
  def loop_path(path: str):
    accum_size = 0.0
    path_list = dbutils.fs.ls(path)
    if path_list:
      for path_object in path_list:
        if path_object.size > 0:
          if verbose:
            print(f"{path_object.path}: {path_object.size / 1e6} MB")
          accum_size += path_object.size / 1e6
        else:
          # Folder: recursive discovery
          accum_size += loop_path(path_object.path)
    return accum_size

  return loop_path(path)

喜歡Emer 的回答

小補充:

如果你遇見

“ModuleNotFoundError:沒有名為‘dbutils’的模塊”

from dbruntime.dbutils而不是from dbutils試試這個。 這個對我有用!

——石正

對於仍然使用@robin loche 的方法達到遞歸限制的任何人,這里是一個純粹的迭代答案:

# from dbutils import FileInfo # Not required in databricks
# from dbruntime.dbutils import FileInfo # may work for some people

def get_size_of_path(path):
    return sum([file.size for file in get_all_files_in_path(path)])

def get_all_files_in_path(path, verbose=False):
    nodes_new = []

    nodes_new = dbutils.fs.ls(path)
    files = []

    while len(nodes_new) > 0:
        current_nodes = nodes_new
        nodes_new = []
        for node in current_nodes:
            if verbose:
                print(f"Processing {node.path}")
            children = dbutils.fs.ls(node.path)
            for child in children:
                if child.size == 0 and child.path != node.path:
                    nodes_new.append(child)
                elif child.path != node.path:
                    files.append(child)
    return files

path = "s3://some/path/"

print(f"Size of {path} in gb: {get_size_of_path(path) / 1024 / 1024 / 1024}")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM