-- опция файлов в pyspark не работает

пробовал sc.addFile опция (работает без каких-либо проблем) и --files опция из командной строки (ошибка).

выполнить 1 : spark_distro.py

from pyspark import SparkContext, SparkConf
from pyspark import SparkFiles

def import_my_special_package(x):
    from external_package import external
    ext = external()
    return ext.fun(x)

conf = SparkConf().setAppName("Using External Library")
sc = SparkContext(conf=conf)
sc.addFile("/local-path/readme.txt")
with open(SparkFiles.get('readme.txt')) as test_file:
    lines = [line.strip() for line in test_file]
print(lines)
int_rdd = sc.parallelize([1, 2, 4, 3])
mod_rdd = sorted(int_rdd.filter(lambda z: z%2 == 1).map(lambda x:import_my_special_package(x)))

внешний пакет: external_package.py

class external(object):
    def __init__(self):
        pass
    def fun(self,input):
        return input*2

readme.txt

MY TEXT HERE

spark-отправить команду

spark-submit 
  --master yarn-client 
  --py-files /path to local codelib/external_package.py  
  /local-pgm-path/spark_distro.py  
  1000

вывод: работает ожидалось

['MY TEXT HERE']

но если я попытаюсь передать файл (readme.txt) из командной строки с помощью --files (вместо sc.addFile) опция не работает. Как внизу.

выполнить 2 : spark_distro.py

from pyspark import SparkContext, SparkConf
from pyspark import SparkFiles

def import_my_special_package(x):
    from external_package import external
    ext = external()
    return ext.fun(x)

conf = SparkConf().setAppName("Using External Library")
sc = SparkContext(conf=conf)
with open(SparkFiles.get('readme.txt')) as test_file:
    lines = [line.strip() for line in test_file]
print(lines)
int_rdd = sc.parallelize([1, 2, 4, 3])
mod_rdd = sorted(int_rdd.filter(lambda z: z%2 == 1).map(lambda x: import_my_special_package(x)))

external_package.py то же, что и выше

Искра представить

spark-submit 
  --master yarn-client 
  --py-files /path to local codelib/external_package.py  
  --files /local-path/readme.txt#readme.txt  
  /local-pgm-path/spark_distro.py  
  1000

выход:

Traceback (most recent call last):
  File "/local-pgm-path/spark_distro.py", line 31, in <module>
    with open(SparkFiles.get('readme.txt')) as test_file:
IOError: [Errno 2] No such file or directory: u'/tmp/spark-42dff0d7-c52f-46a8-8323-08bccb412cd6/userFiles-8bd16297-1291-4a37-b080-bbc3836cb512/readme.txt'

и sc.addFile и --file используется для тех же цель? Кто-нибудь, пожалуйста, поделитесь своими мыслями.

4 ответов


я, наконец, понял проблему, и это очень тонкие действительно.

как и предполагалось, два варианта (sc.addFile и --files) составляют не эквивалент, и это (по общему признанию, очень тонко) намекает на документацию (курсив добавлен):

addFile(путь, рекурсивный=False)
Добавьте файл для загрузки с помощью этого задания Spark на каждом узел.

--files файлы
Разделенный запятыми список файлов, которые будут помещены в рабочих каталог каждого исполнитель.

на простом английском языке, в то время как файлы, добавленные с sc.addFile доступны как исполнителям, так и водителю, файлы добавлены с --files доступны только исполнителям; следовательно, при попытке доступа к ним из драйвера (как это имеет место в OP) мы получаем No such file or directory ошибка.

давайте подтвердите это (избавляясь от всего неуместного --py-files и 1000 материал в OP):

test_fail.py:

from pyspark import SparkContext, SparkConf
from pyspark import SparkFiles

conf = SparkConf().setAppName("Use External File")
sc = SparkContext(conf=conf)
with open(SparkFiles.get('readme.txt')) as test_file:  
    lines = [line.strip() for line in test_file]
print(lines)

тест:

spark-submit --master yarn \
             --deploy-mode client \
             --files /home/ctsats/readme.txt \
             /home/ctsats/scripts/SO/test_fail.py

результат:

[...]
17/11/10 15:05:39 INFO yarn.Client: Uploading resource file:/home/ctsats/readme.txt -> hdfs://host-hd-01.corp.nodalpoint.com:8020/user/ctsats/.sparkStaging/application_1507295423401_0047/readme.txt
[...]
Traceback (most recent call last):
  File "/home/ctsats/scripts/SO/test_fail.py", line 6, in <module>
    with open(SparkFiles.get('readme.txt')) as test_file:
IOError: [Errno 2] No such file or directory: u'/tmp/spark-8715b4d9-a23b-4002-a1f0-63a1e9d3e00e/userFiles-60053a41-472e-4844-a587-6d10ed769e1a/readme.txt'

в приведенном выше скрипте test_fail.py, это водитель программа, которая запрашивает доступ к файлу readme.txt; Давайте изменим сценарий, так что доступ запрашивается для исполнители (test_success.py):

from pyspark import SparkContext, SparkConf

conf = SparkConf().setAppName("Use External File")
sc = SparkContext(conf=conf)

lines = sc.textFile("readme.txt") # run in the executors
print(lines.collect())

тест:

spark-submit --master yarn \
             --deploy-mode client \
             --files /home/ctsats/readme.txt \
             /home/ctsats/scripts/SO/test_success.py

результат:

[...]
17/11/10 15:16:05 INFO yarn.Client: Uploading resource file:/home/ctsats/readme.txt -> hdfs://host-hd-01.corp.nodalpoint.com:8020/user/ctsats/.sparkStaging/application_1507295423401_0049/readme.txt
[...]
[u'MY TEXT HERE']

обратите внимание также, что здесь нам не нужно SparkFiles.get - файл доступен.

как сказали выше, sc.addFile будет работать в обоих случаях, т. е. когда доступ запрашивается либо драйвером, либо исполнителями (проверено, но не показано здесь).

что касается порядка параметров командной строки: как я утверждал везде все Аргументы, связанные с Spark, должны быть перед исполняемым скриптом; возможно, относительный порядок --files и --py-files не имеет значения (оставляя это в качестве упражнения).

проверено с обоими Искра 1.6.0 & 2.2.0.

обновление (после комментариев): кажется, что мой fs.defaultFS установка точек на HDFS тоже:

$ hdfs getconf -confKey fs.defaultFS
hdfs://host-hd-01.corp.nodalpoint.com:8020

но позвольте мне сосредоточиться на леса здесь (вместо деревьев, то есть), и объяснить почему вся эта дискуссия представляет только академический интерес:

передает файлы для обработки С --files флаг-плохая практика; оглядываясь назад, я теперь понимаю, почему я не мог найти почти никаких ссылок в интернете - вероятно, никто не использует его на практике, и не без оснований.

(обратите внимание, что я говорю не для --py-files, который выполняет другую, законную роль.)

поскольку Spark-это распределенная платформа обработки, работающая над кластер и распределенная файловая система (HDFS), лучшее, что нужно сделать, это иметь все файлы для обработки в HDFS уже - период. "Естественным" местом для обработки файлов Spark является HDFS, а не локальная FS - хотя есть некоторые игрушки примеры использования локальных FS только для демонстрационных целей. Более того, если вы хотите в будущем изменить режим развертывания на cluster, вы обнаружите, что кластер по умолчанию ничего не знает локальных путей и файлов, и по праву...


та же цель, но разные использования.

С --files опции

 --files FILES               Comma-separated list of files to be placed in the working
                              directory of each executor.

не нужно SparkFiles.get получить расположение файла, потому что это на самом деле в working directory of each executor.

with open('readme.txt') as test_file:
    lines = [line.strip() for line in test_file]

попробовать

import os
from os import path

here = os.getcwd()
with open(path.join(here, 'readme.txt')) as f:
    pass

читайте Подачи Заявок снова, он сказал:

для приложений Python просто передайте .py-файл вместо банки и добавьте Python .промелькнуть. ,яйцо или .py-файлы в путь поиска с --py-файлами.

search path ключ


передайте этот файл в качестве аргумента при его использовании в spark-submit как sc = SparkContext(conf=conf) with open(SparkFiles.get(args(0))) as test_file: в программе и в spark submit

spark-submit \
  --master yarn-client \ 
  /local-pgm-path/spark_distro.py  \
  /local/file/path

путь к файлу должен прийти после файла jar приложения.