正在从多个文件夹中读取文件,然后使用python sdk和数据流运行器将文件名(文件内容,文件名)之类的文件内容输出到apache beam中的bigquery。
本来以为我可以为每个文件创建一个pcollection,然后将文件内容与文件名映射。
def read_documents(pipeline):
"""Read the documents at the provided uris and returns (uri, line) pairs."""
pcolls = []
count = 0
with open(TESTIN) as uris:
for uri in uris:
#print str(uri).strip("[]/'")
pcolls.append(
pipeline
| 'Read: uri' + str(uri) >>ReadFromText(str(uri).strip("[]/'"), compression_type = 'gzip')
| 'WithKey: uri' + str(uri) >> beam.Map(lambda v, uri: (v, str(uri).strip("[]")), uri)
)
return pcolls | 'FlattenReadPColls' >> beam.Flatten()
这可以正常工作,但是速度很慢,并且在大约10000个文件之后无法在数据流云上工作。如果文件超过10000个,它将遭受管道破裂的困扰。
当前试图从Text.io重载ReadAllFromText函数。 Text.io旨在从大量文件名或模式中快速读取大量文件。如果从Google云端存储中读取文件并且文件具有内容编码,则此模块中存在错误。 Google云端存储会自动对文件进行Gunzip压缩并进行转码,但由于某些原因,ReadAllFromText无法使用它。您必须更改文件的元数据以删除内容编码,并将ReadAllFromText上的压缩类型设置为gzip。如果其他人对ReadAllFromText有问题,我会提供此问题的网址 https://issues.apache.org/jira/browse/BEAM-1874
我当前的代码如下
class ReadFromGs(ReadAllFromText):
def __init__(self):
super(ReadFromGs, self).__init__(compression_type="gzip")
def expand(self, pvalue):
files = self._read_all_files
return (
pvalue
| 'ReadAllFiles' >> files #self._read_all_files
| 'Map values' >> beam.Map( lambda v: (v, filename)) # filename is a placeholder for the input filename that im trying to figure out how to include in the output.
)
ReadAllFromText包含在Text.io中,并从filebasedsource.py调用ReadAllText并从PTransform继承。
我相信我只是缺少一些简单的缺失。
https://github.com/apache/beam/blob/master/sdks/python/apache_beam/io/filebasedsource.py
https://github.com/apache/beam/blob/master/sdks/python/apache_beam/io/textio.py
答案 0 :(得分:2)
如您所见,ReadFromText
当前不支持动态文件名,并且您绝对不想为每个URL创建单独的步骤。从您的第一句话开始,我了解到您希望将文件名和文件内容作为一项输出。这意味着您将不需要文件部分的任何流或从中受益。您可以简单地读取文件内容。像这样:
import apache_beam as beam
from apache_beam.io.filesystems import FileSystems
def read_all_from_url(url):
with FileSystems.open(url) as f:
return f.read()
def read_from_urls(pipeline, urls):
return (
pipeline
| beam.Create(urls)
| 'Read File' >> beam.Map(lambda url: (
url,
read_all_from_url(url)
))
)
如果您认为元数据有问题,可以自定义它。输出将是一个元组( url ,文件内容)。如果您的文件内容很大,您可能需要根据使用情况使用稍微不同的方法。