【问题标题】:How to calculate a Directory size in ADLS using PySpark?如何使用 PySpark 计算 ADLS 中的目录大小?
【发布时间】:2020-08-02 08:13:26
【问题描述】:

我想计算一个包含子文件夹和子文件的目录(例如 XYZ)大小。 我想要 XYZ 中所有文件和所有内容的总大小。

我可以找出特定路径中的所有文件夹。但我想要所有的大小。 我也看到了

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

给我 abc 文件的数据大小。 但我想要 XYZ 的完整尺寸。

【问题讨论】:

  • du -h 不起作用?
  • 能否请您更清楚地回答您的问题?
  • du -h 目录路径

标签: python apache-spark pyspark databricks azure-databricks


【解决方案1】:

@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)

【讨论】:

    【解决方案2】:

    尝试使用 dbutils ls 命令,获取数据框中的文件列表并在 size 列上使用聚合函数 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"))
    

    【讨论】:

      【解决方案3】:

      dbutils.fs.ls 没有像 cpmvrm 这样的递归功能。因此,您需要自己迭代。这是一个将为您完成任务的 sn-p。从 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
      

      【讨论】:

      • 知道为什么这个解决方案不适用于更大的目录吗?
      • 首先我看到 OOM 问题并添加了 sys.setrecursionlimit(2000)。现在,“RecursionError:比较中超出了最大递归深度”
      • 路径必须很深,在到达文件之前,您可能有很多“子目录”。尝试将 2k 增加到 500k 之类的大值。我稍后会尝试把它捡起来
      猜你喜欢
      • 2010-11-26
      • 1970-01-01
      • 2011-03-11
      • 2017-02-06
      • 2018-03-29
      • 1970-01-01
      • 1970-01-01
      • 2019-04-22
      相关资源
      最近更新 更多