我无法使用" DirectPipelineRunner"在本地运行我的管道。但是当我使用" BlockingDataflowPipelineRunner"要在云上运行它总是显示"无法拆分源"。我不知道我的管道问题在哪里。
我定义了我的自定义源来读取我的存储桶中的大量tgz文件。以下是我的代码。
loop 3
loop 2
loop 1
loop 1
这是我的管道
class My_Compressed_Source(filebasedsource.FileBasedSource):
def read_records(self, file_name, range_tracker):
import tarfile
import re
start_offset = range_tracker.start_position()
with self.open_file(file_name) as f:
tar = tarfile.open(fileobj = f)
for member in tar.getmembers():
f = tar.extractfile(member)
content = f.read()
# do some regular expression process to content
另外,我的输入路径是" - 输入gs://mybucket/source/*.tgz"我的职位是" 2016-10-14_09_21_43-4409773810679481086"。 我想知道我应该设置" splittable"真的。或者如果有什么不对劲。
答案 0 :(得分:1)
由于必须将所有数据加载到内存中,因此不建议使用上面提到的StringIO读取tar文件。
似乎你的原始实现没有工作,因为tarfile.open()使用方法seek()和tell()不受filebasedsource.open_file()返回的fileio._CompressedFile对象的支持。
答案 1 :(得分:0)
感谢上述所有评论
我尝试了几种方法来解决我的问题。我有一点进步。我认为有必要再次描述我的问题
我添加了compression_type参数并将其设置为fileio.CompressionTypes.GZIP
。如下所示。
pcoll = p | "Read" >> beam.io.Read(My_Compressed_Source(args.input, split = False, compression_type = fileio.CompressionTypes.GZIP))
pcoll | beam.ParDo('parse tar member', Parse_Members())
p.run()
我尝试通过“DirectPipelineRunner”在本地执行它,并且tarfile.open()显示错误。所以我将read_records函数修改为以下版本。
class My_Compressed_Source(filebasedsource.FileBasedSource):
def read_records(self, file_name, range_tracker):
import tarfile
import re
import StringIO
start_offset = range_tracker.start_position()
f = self.open_file(file_name)
start = range_tracker.start_position
text_str = str(f.read(f._read_size))
tar = tarfile.open(fileobj=StringIO.StringIO(text_str), bufsize=f._read_size)
for mem in tar.getmembers():
print mem.name
我指定f.read()的字节数来获取我的tgz文件的全部内容。现在文件只是tar。
然后我使用StringIO模块创建一个临时的file_obj来放入tarfile.open。最后,我使用循环访问文件的每个名称。我确实提取了一些文件名,但只访问了一些文件。
尝试不同的数据源后,我认为关键是无论源是什么,f._read_size的长度总是最大为16384 = 16k。我想知道如果有一些设置缓冲区大小的最大值可以让我访问整个内容,或者我应该尝试另一种方式?