【问题标题】:How to save a file on the cluster如何在集群上保存文件
【发布时间】:2018-05-29 11:03:54
【问题描述】:

我使用ssh 连接到集群,并使用

将程序发送到集群
spark-submit --master yarn myProgram.py

我想将结果保存在文本文件中,我尝试使用以下行:

counts.write.json("hdfs://home/myDir/text_file.txt")
counts.write.csv("hdfs://home/myDir/text_file.csv")

但是,它们都不起作用。程序结束,我在myDir 中找不到文本文件。你知道我该怎么做吗?

另外,有没有办法直接写入我的本地机器?

编辑:我发现home 目录不存在,所以现在我将结果保存为: counts.write.json("hdfs:///user/username/text_file.txt") 但这会创建一个名为text_file.txt 的目录,在里面我有很多文件,里面有部分结果。但我想要一个包含最终结果的文件。有什么想法可以做到这一点吗?

【问题讨论】:

  • 你能显示hdfs dfs -ls hdfs://home/myDir的输出吗?
  • 另外,如果Spark使用HDFS作为默认文件系统,你只需要/home/myDir写入
  • -ls: java.net.UnknownHostException: home 所以我猜这个文件夹不存在。通常当我将文件保存在目录中时,我应该把它放在哪里?
  • 你可以把它放在任何地方... HDFS 默认是空的。但是/home是Linux用户目录....在HDFS中,它是/user
  • UnknownHostException 是因为您的路径错误。应该是hdfs:///home/myDir,或者最好从任何地方删除hdfs://,如前所述

标签: python apache-spark pyspark hdfs spark-submit


【解决方案1】:

您可以从命令行将结果连接到一个文件中:

hadoop fs -cat hdfs:///user/username/text_file.txt/* > path/to/local/file.txt

这应该比使用coalesce 更快——根据我的经验,所有collect() 类型的操作都很慢,因为所有数据都通过主节点汇集。此外,如果您的数据超出主节点上的内存,您可能会遇到collect() 的麻烦。

然而,这种方法的一个潜在缺陷是您必须从先前的运行中显式删除文件(因为当前运行可能不会产生完全相同数量的文件)。每次运行都可能有一个标志来执行此操作,但我不确定。

删除:

hadoop fs -rm -r hdfs:///user/username/text_file.txt/*

【讨论】:

    【解决方案2】:

    要拥有一个唯一的文件(不是您想要的名称),您需要 .repartition(1),look here,通过管道传输到您的 RDD。 我想你的hdfs路径是错误的。在 Spark HDFS 中,文本文件是默认的,而在 Hadoop 中(默认情况下),根目录中没有主目录,除非您之前创建过它。 如果您想要一个 csv/txt 文件(带有此扩展名),那么编写它的唯一方法是不使用 RDD 或 DF 函数,而是使用 Python csv 和 io 的常用库,在您使用 .collect() 收集之后,您的 RDD在一个 martix 中(数据集不是很大)。

    如果您想直接在文件系统(而不是 HDFS)上写入,请使用

    counts.write.csv("file:///home/myDir/text_file.csv")
    

    但这不会写入带有 csv 扩展名的单个文件。它将创建一个文件夹,其中包含数据集 n 个分区的 part-m-0000n。

    【讨论】:

      【解决方案3】:

      由于计算是分布式的,Spark 会将结果保存在多个文件中。因此写作:

      counts.write.csv("hdfs://home/myDir/text_file.csv")
      

      表示将每个分区上的数据作为单独的文件保存在文件夹text_file.csv中。如果要将数据保存为单个文件,请先使用coalesce(1)

      counts.coalesce(1).write.csv("hdfs://home/myDir/text_file.csv")
      

      这会将所有数据放在一个分区中,因此保存的文件数将为 1。但是,如果您有很多数据,这可能是个坏主意。如果数据非常小,则使用collect() 是一种替代方法。这会将所有数据作为数组放入驱动程序机器上,然后可以将其保存为单个文件。

      【讨论】:

      • 您可以使用:counts.repartition(1).write.csv("hdfs://home/myDir/text_file.csv")。但请注意repartition 算法对数据进行完全洗牌并创建大小相等的数据分区。 coalesce 结合现有分区以避免完全洗牌。 repartition 方法可用于增加或减少 DataFrame 中的分区数。但是coalesce算法显然不能创建分区数。
      【解决方案4】:

      你有什么错误吗?也许您可以检查您是否具有从该文件夹写入/读取的正确权限。

      还认为 Spark 默认会创建一个名为 text_file.txt 的文件夹,其中包含一些文件,具体取决于您拥有的分区数量。

      如果你想在本地机器上写,你可以用file:///home/myDir/text_file.txt指定路径。如果你使用像/user/hdfs/...这样的路径,默认情况下是写在HDFS中

      【讨论】:

      • 我可以从终端检查我是否有写权限吗?我在 Mac 上
      • 您可以使用hdfs dfs -ls /home/myDir查看文件夹的权限和所有者,还可以在运行spark-submit时检查您使用的是哪个用户。也许您可以尝试将/user/spark/... 用作文件夹而不是/home。 HDFS 中默认不存在 Home 文件夹。
      • 您如何将整个结果写入一个 txt 文件?因为正如你所说,它创建了一个目录,在里面我有部分结果。但我只想要一个包含最终结果的文件。
      • Shaido 的回应是您只需要创建一个文件。在任何情况下,Spark 都会创建一个名为 text_file.csv 的文件夹,其中只有一个文件。
      猜你喜欢
      • 2016-03-18
      • 2022-01-08
      • 1970-01-01
      • 2021-12-10
      • 2017-02-14
      • 2018-08-24
      • 2021-08-12
      • 2018-03-09
      • 2020-06-02
      相关资源
      最近更新 更多