我对PySpark很新,我正在尝试加载和预处理一些数据。但是,有些数据似乎已损坏,我需要处理这些错误,同时找出哪些文件已损坏。
def load_audio(path, sr = 22050):
return librosa.load(path,sr=sr)
rdd = sc.parallelize(paths) #Path to all files
audio = rdd.map(lambda path: (path,load_audio(os.path.join(std_audio_path,path)))) # Loads all the audio files
只要load_audio
尝试加载损坏的文件,程序就会崩溃。我意识到尝试和捕获可以工作但我无法看到它在这种情况下如何解决我的问题。
我理想的是加载所有未损坏的文件。我想要加载的文件路径损坏/抛出错误进入自己的rdd /列表。
我怎样才能做到这一点? :)
答案 0 :(得分:2)
尝试/除了轻松解决您的问题。我们可以在这里使用oldschool / Go思维模式,而异常函数会返回错误代码或类似的实际结果。
我没有你的文件重现,所以我会使用只检查路径的函数创建类似的错误,当文件是mp3时抛出异常。我们说我有文件列表:
import random
paths = [str(i) + '.' + random.choice(('mp3', 'ogg')) for i in xrange(100)]
std_audio_paths = '/'
def load_audio(path, sr=22050):
if path.endswith('mp3'):
raise IOError('Unknown format')
return 'audio data'
rdd = sc.parallelize(paths)
audio = rdd.map(lambda path: (path,load_audio(os.path.join(std_audio_path,path))))
audio.collect()
# will break because load_audio throws exception
所以我会使用try / except来创建不会引发异常的load_audio
包装,但会返回错误:
def try_to_load_audio(path):
try:
return load_audio(path), None
except IOError as e:
return '', 'error'
audio = rdd.map(lambda path: (path,try_to_load_audio(os.path.join(std_audio_path,path))))
audio.collect()
# returns collection of pairs (path, (result, error)):
# [('0.mp3', ('', 'error')), ('1.ogg', ('audio data', None)), ...
现在问题的第二部分。执行collect()
而不是audio.cache()
,因此您不会两次加载文件,然后:
failed = audio.filter(lambda f: f[1][1] == 'error').map(lambda f: f[0])
failed.collect()
# gives paths only of failed files (mp3 in my case):
# ['0.mp3', '3.mp3', ...
只加载音频数据:
loaded_data = audio.filter(lambda f: f[1][1] is None).map(lambda f: f[1][0])
loaded_data.collect()
# Gives ['audio data', 'audio data',...