在DataFlow上运行光束管道时,关闭后文件将被覆盖

时间:2019-03-01 17:06:44

标签: python pickle apache-beam dataflow dill

我创建了一个束流管道p,该束流可以在数据流上运行,并且想要在运行管道之前向文件中写入一些内容。我的代码是:

import apache_beam as beam
from apache_beam.options.pipeline_options import PipelineOptions
from apache_beam.options.pipeline_options import SetupOptions
import time

pipeline_options = PipelineOptions(runner='DirectRunner')
pipeline_options.view_as(SetupOptions).save_main_session = True
p = beam.Pipeline(options=pipeline_options)

myString = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

myFile3984573498534 = open('myfile2398457erity348t67349856734986739846.txt','w+')
myFile3984573498534.write(myString*100)
myFile3984573498534.close()

time.sleep(1)

r = p.run()

文件已正确写入,但是一旦调用p.run(),它就会被覆盖为空白。谁能解释为什么会这样?

注意:

  • 更改文件名和文件变量名不会影响结果。
  • 我已插入time.sleep(1),以便可以在调用p.run()之前将文件视为已写入并且文件被覆盖为空白。这不是必需的,可以更改/删除。

1 个答案:

答案 0 :(得分:0)

问题来自pipeline_options.view_as(SetupOptions).save_main_session = True行。

当管道运行时,beam将使用dill.dump_session来序列化主会话并将其保存到文件中。然后它将使用dill.load_session加载相同的文件并反序列化以重新创建主会话。它将使用dill.dump_session重新序列化主会话,以发送给跑步者。序列化,反序列化然后重新序列化主会话的原因是为了解决序列化中的不一致问题,如https://github.com/uqfoundation/dill/issues/195中所述。这意味着所有跑步者都会遇到这个问题。

在这种情况下,主会话包含myFile3984573498534文件对象。反序列化后,它将使用w+模式以与您最初打开文件时相同的方式重新打开文件。这将立即覆盖该文件。然后关闭此文件,并且管道以文件空白结束。

对此的最佳解决方法是在r+模式下打开文件,以便在对主会话进行反序列化期间以读取模式打开文件,从而不会对其进行修改。

如果需要w+模式打开文件,则应在关闭文件后删除存储文件的变量,即del(myFile3984573498534)之后的myFile3984573498534.close() 但是在运行管道之前。这样可以防止变量因为不再存在而被序列化,从而导致文件未被修改。