Как сохранить файл на кластере

Я подключаюсь к кластеру с помощью 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, и внутри у меня есть много файлов с частичными результатами внутри. Но я хочу один файл с окончательным результатом внутри. Любые идеи, как я могу это сделать?


person lads    schedule 15.12.2017    source источник
comment
Не могли бы вы показать вывод hdfs dfs -ls hdfs://home/myDir?   -  person OneCricketeer    schedule 16.12.2017
comment
Кроме того, если Spark использует HDFS в качестве файловой системы по умолчанию, вам нужно только /home/myDir для записи в   -  person OneCricketeer    schedule 16.12.2017
comment
-ls: java.net.UnknownHostException: home так что я думаю, что этой папки не существует. Обычно, когда я должен сохранить файл в каталоге, я должен его поместить?   -  person lads    schedule 16.12.2017
comment
Вы можете разместить его где угодно... По умолчанию HDFS пуста. Но /home - это пользовательский каталог Linux... В HDFS это /user.   -  person OneCricketeer    schedule 16.12.2017
comment
UnknownHostException потому что ваш путь неверен. Должно быть hdfs:///home/myDir, а лучше убрать hdfs:// отовсюду, как упоминалось   -  person OneCricketeer    schedule 16.12.2017
comment
@cricket_007 Теперь я понимаю, что домашнего каталога не существует, но я могу сохранить его в /user/username. Но могу ли я сохранить его как файл, а не как каталог?   -  person lads    schedule 16.12.2017


Ответы (4)


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(). Это поместит все данные на машину водителя в виде массива, который затем можно будет сохранить в виде одного файла.

person Shaido    schedule 18.12.2017
comment
Вы можете использовать: counts.repartition(1).write.csv("hdfs://home/myDir/text_file.csv"). Но обратите внимание, что алгоритм repartition полностью перемешивает данные и создает разделы данных одинакового размера. coalesce объединяет существующие разделы, чтобы избежать полного перемешивания. Метод repartition можно использовать для увеличения или уменьшения количества разделов в DataFrame. Однако алгоритм coalesce, очевидно, не может увеличить количество разделов. - person deadbug; 24.12.2017

Вы можете объединить свои результаты в один файл из командной строки:

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/*
person pault    schedule 21.12.2017

Вы получаете какую-либо ошибку? Возможно, вы можете проверить, есть ли у вас правильные права на запись/чтение из этой папки.

Также помните, что Spark по умолчанию создаст папку с именем text_file.txt с некоторыми файлами внутри, в зависимости от количества разделов, которые у вас есть.

Если вы хотите писать на своем локальном компьютере, вы можете указать путь с помощью file:///home/myDir/text_file.txt. Если вы используете путь типа /user/hdfs/... по умолчанию пишется в HDFS

person Javier Montón    schedule 15.12.2017
comment
Могу ли я проверить с терминала, есть ли у меня разрешение на запись? я на мак - person lads; 15.12.2017
comment
Вы можете использовать hdfs dfs -ls /home/myDir, чтобы увидеть разрешения и владельца папки, а также проверить, какого пользователя вы используете при запуске spark-submit. Может быть, вы могли бы попробовать использовать папку /user/spark/... вместо /home. Домашняя папка не существует по умолчанию в HDFS. - person Javier Montón; 15.12.2017
comment
Как я могу записать весь результат в один текстовый файл? Потому что, как вы сказали, он создает каталог, и внутри у меня есть частичные результаты. Но я хочу только один файл с окончательным результатом внутри. - person lads; 18.12.2017
comment
Ответ от Shaido заключается в том, что вам нужно создать только один файл. В любом случае Spark создаст папку с именем text_file.csv, содержащую только 1 файл внутри. - person Javier Montón; 18.12.2017

Чтобы иметь уникальный файл (не названный так, как вы хотите), вам нужно .repartition(1),смотрите здесь, переданный в ваш 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. Он создаст папку с частью-m-0000n из n разделов вашего набора данных.

person CarloV    schedule 19.12.2017