![](/img/trans.png)
[英]KeyError on passing PCollection as side input on Apache Beam
[英]What does flatmap in apache beam exactly do to the input pcollection when returning to the caller?
我使用的Apache光束2.10,并试图了解究竟flatmap被返回pcollection给调用者的时候做。
阅读在线文档中的解释后,我认为flatMap可以像本示例一样将PCollection元素集合简单地拆分为单个pcollection。
可调用对象必须为输入PCollection的每个元素返回一个可迭代的对象。 这些可迭代对象的元素将被展平到输出PCollection中。
但是在以下代码的情况下, flatMap展平“ Hello World”的每个字符,而不是整体返回“ Hello World”。
def simple(x):
logging.info("Inside simple type: {0}, val: {1}".format(type(x), x))
# Just return
return x
def run():
with beam.Pipeline(runner='DirectRunner') as p:
elems = p | 'map:init' >> beam.Create(["Hello World"])
#
# Sample with FlatMap
#
( elems | 'flatmap:exec' >> beam.FlatMap(simple) # 1 to 1 relation with flatmap
| 'flatmap:out' >> beam.io.textio.WriteToText(file_path_prefix='flatmap')
)
def main():
run()
if __name__ == "__main__":
main()
H
e
l
l
o
W
o
r
l
d
但是,当我返回一个生成器时 ,就像下面的代码一样,迭代的结果似乎变成了pcollection。
def simple(x):
logging.info("Inside simple type: {0}, val: {1}".format(type(x), x))
# Just return
yield x
def run():
with beam.Pipeline(runner='DirectRunner') as p:
elems = p | 'map:init' >> beam.Create(["Hello World"])
#
# Sample with FlatMap
#
( elems | 'flatmap:exec' >> beam.FlatMap(simple) # 1 to 1 relation with flatmap
| 'flatmap:out' >> beam.io.textio.WriteToText(file_path_prefix='flatmap')
)
def main():
run()
if __name__ == "__main__":
main()
Hello World
如果我从字面上返回一个迭代器,则将迭代一个字符串,并将每个字符展平为PCollections。
def simple(x):
logging.info("Inside simple type: {0}, val: {1}".format(type(x), x))
# Just return
return iter(x)
def run():
with beam.Pipeline(runner='DirectRunner') as p:
elems = p | 'map:init' >> beam.Create(["Hello World"])
#
# Sample with Map
#
( elems | 'flatmap:exec' >> beam.FlatMap(simple) # 1 to 1 relation with flatmap
| 'flatmap:out' >> beam.io.textio.WriteToText(file_path_prefix='flatmap')
)
def main():
run()
if __name__ == "__main__":
main()
H
e
l
l
o
W
o
r
l
d
那么,在将PCollection返回给调用者函数时,flatMap到底能做什么?
FlatMap
假定给定函数的返回类型是iterable
。 在第一个示例中, simple
返回"Hello World"
。 作为iterable
, "Hello World"
可以被视为['H','e','l','l','o',' ','W','o','r','l','d']
。 因此,第一个示例的工作方式如下:
[] -> create -> ["Hello World"]
["Hello World"] -> map -> [['H','e','l','l','o',' ','W','o','r','l','d']]
[['H','e','l','l','o',' ','W','o','r','l','d']] -> flatten -> ['H','e','l','l','o',' ','W','o','r','l','d']
最终PCollection: ['H','e','l','l','o',' ','W','o','r','l','d']
但是,在第二个示例中, simple
得出x
。 您可以认为simple
返回包含单个元素x
iterator
。 因此,您的第二个示例是这样的:
[] -> create -> ["Hello World"]
["Hello World"] -> map -> [["Hello World"]]
[["Hello World"]] -> flatten -> ["Hello World"]
最终PCollection: ["Hello World"]
要回答您的最后一个问题:
yield x
和return iter(x)
在语义上是不同的。 以下示例可以帮助您理解上下文。
>>> list(iter("abc"))
['a', 'b', 'c']
>>> def x(): yield "abc"
>>> list(x())
['abc']
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.