我正在尝试做一些本来应该很简单但却无法做到的事情。
我在客户的FTP服务器中有一个.csv文件。路径是这样的:
ftp://[user]:[passwd]@[IP-ADDRESS]/file.csv
通过复制和粘贴地址,我可以轻松地在我的浏览器(或任何其他程序)上访问该文件。但是我不能在pyspark上访问它。
以下是我要做的事情,使用数据库spark-csv(https://github.com/databricks/spark-csv):
file_path = ftp://[user]:[passwd]@[IP-ADDRESS]/file.csv
reader = sqlContext.read.format('com.databricks.spark.csv')
.options(header=False, charset='cp860', inferschema='true', delim=";")
.load(file_path)
我收到以下错误:
org.apache.hadoop.mapred.InvalidInputException: Input path does not exist: ftp://[user]:[passwd]@[IP-ADDRESS]/file.csv
尝试将文件作为文本文件读取:
df = sqlContext.read.text("ftp://[user]:[passwd]@[IP-ADDRESS]/SALES_37_TIRADENTES_2016-09-01.csv", )
df.collect()
错误:
Py4JJavaError: An error occurred while calling o147.collectToPython.
: java.io.IOException: No input paths specified in job
我很确定这与FTP访问有关,但我不确定。
我最终使用Python的ftplib
下载文件并将文件加载到RDD中。如果数据的大小太大,可能是次优的方法,但它可以工作。
答案 0 :(得分:2)
您可以使用 SparkFiles 从FTP使用文件 http://spark.apache.org/docs/latest/api/python/pyspark.html
<强> addFile(路径)强>
在每个节点上添加要使用此Spark作业下载的文件。传递的路径可以是本地文件,HDFS(或其他Hadoop支持的文件系统)中的文件,也可以是HTTP,HTTPS或FTP URI。
要在Spark作业中访问该文件,请使用带有文件名的L {SparkFiles.get(fileName)}来查找其下载位置。
>>> from pyspark import SparkFiles
>>> path = os.path.join(tempdir, "test.txt")
>>> with open(path, "w") as testFile:
... _ = testFile.write("100")
>>> sc.addFile(path)
>>> def func(iterator):
... with open(SparkFiles.get("test.txt")) as testFile:
... fileVal = int(testFile.readline())
... return [x * fileVal for x in iterator]
>>> sc.parallelize([1, 2, 3, 4]).mapPartitions(func).collect()
[100, 200, 300, 400]
以下测试(pyspark - 1.5.2)正在运行:
from pyspark import SparkFiles
file_path = "ftp://ftp:ftp@ftp.ed.ac.uk/pub/Unix/Win2000_PlainPassword.reg"
sc.addFile(file_path)
filename = SparkFiles.get(file_path.split('/')[-1])
rdd = sc.textFile("file://"+filename)
rdd.take(10)
rdd.collect()
答案 1 :(得分:0)
这里有一些可能有用的东西(scala版本,使用spark 1.6.3测试)
首先使用Spark上下文中的 wholeTextFiles 方法获取文件
val dataSource = "ftp://[user]:[passwd]@[IP-ADDRESS]"
val fileRDD = sc.wholeTextFiles(dataSource).values
然后使用您的选项
实例化CsvParserval csvParser: CsvParser = new CsvParser().withUseHeader(true).withInferSchema(true).withDelimiter(';').withCharset("cp860")
(如果您不想使用标题,请不要忘记删除第一行)
最后
val df = csvParser.csvRdd(sq, fileRDD)
df.collect()
希望这有帮助!