返回调用者时,apache Beam中的flatmap对输入pcollection到底有什么作用?

时间:2019-05-01 02:53:17

标签: python apache-beam

我正在使用 apache Beam 2.10 并试图了解将{p3}返回给调用者时flatmap到底在做什么。

在阅读在线文档的说明后,我认为 flatMap 就像在this示例中那样,将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

但是当我返回一个 generator 时,就像在这个code中那样,迭代的结果似乎变成了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

于JST于2019年5月2日添加

如果我从字面上返回一个 iterator ,则将迭代一个字符串,并将每个字符展平为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到底能做什么?

1 个答案:

答案 0 :(得分:1)

FlatMap假定给定函数的返回类型为iterable。在第一个示例中,simple返回"Hello World"。与iterable一样,"Hello World"可以视为['H','e','l','l','o',' ','W','o','r','l','d']。因此,您的第一个示例的工作方式如下:

  1. [] -> create -> ["Hello World"]
  2. ["Hello World"] -> map -> [['H','e','l','l','o',' ','W','o','r','l','d']]
  3. [['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返回iterator,其中包含单个元素x。所以您的第二个示例是这样的:

  1. [] -> create -> ["Hello World"]
  2. ["Hello World"] -> map -> [["Hello World"]]
  3. [["Hello World"]] -> flatten -> ["Hello World"]

最终PCollection:["Hello World"]

要回答您的最后一个问题:

yield xreturn iter(x)在语义上是不同的。以下示例可以帮助您理解上下文。

>>> list(iter("abc"))
['a', 'b', 'c']
>>> def x(): yield "abc"
>>> list(x())
['abc']