管道输出从子进程到文件,然后再读回

时间:2012-03-12 13:02:49

标签: python subprocess

我有一个python脚本,它运行一个子进程来获取一些数据然后处理它。我想要实现的是将数据写入文件,然后使用文件中的数据进行处理(原因是子进程很慢,但可以根据日期,时间和参数进行更改我用,我需要经常运行脚本)

我尝试了各种方法,包括将文件打开为w+并尝试在写入完成后寻找开头,但似乎没有任何工作 - 文件被写入,但是当我尝试阅读时从它回来(使用file.readline())我得到了EOF。

这是我基本上要完成的事情:

      myFile = open(fileName, "w")
      p = subprocess.Popen(args, stdout=myFile)
      myFile.flush()    # force the file to disk
      os.fsync(myFile)  # ..
      myFile.close()

      myFile = open(fileName, "r")
      while myFile.readline():
        pass # do stuff
      myFile.close()

但即使文件写得正确(脚本运行后,我可以看到文件的内容),readline永远不会返回有效行。就像我说的那样,我也试过使用相同的文件对象,并在其上做seek(0),没有运气。这仅在以r+打开文件时有效,当文件尚不存在时失败。

任何帮助将不胜感激。此外,如果有一个更清洁的方法来做到这一点,我愿意接受它:)

PS:我意识到我可以Popenstdout来管道,从管道中读取然后逐行将数据写入文件,但我正在尝试将数据文件的创建与阅读分开。

3 个答案:

答案 0 :(得分:2)

在尝试从文件中读取之前,子进程几乎肯定没有完成。事实上,在您尝试从文件中读取之前,子进程可能甚至不会。对于真正的分离,您必须将子进程写入临时文件,然后替换您从中读取的文件,以便您可以读取以前的版本或新版本,但是永远不会看到部分写入的文件。新版本。

你可以通过多种方式做到这一点;最简单的方法是更改​​子进程,但我不知道这是否适合您。或者,您可以将其包装在您自己的单独脚本中以管理文件。您可能不希望在分析输出文件的脚本中调用子进程;你会想要一个cronjob或其他东西定期再生。

答案 1 :(得分:0)

如果子流程正在及时完成,这应该可以正常工作(参见James的回答)。

如果您想等待它完成,请在p.wait()调用后添加Popen

但是你的实际循环是什么? while myFile.readline()看起来似乎没有为任何事情保存线路。试试这个:

myFile = open(fileName, "r")
print myFile.readlines()
myFile.close()

或者,如果您想以交互方式检查程序的状态:

myFile = open(fileName, "r")
import pdb; pdb.set_trace()
myFile.close()

然后,您可以在print myFile.readlines()停止后执行此操作。

答案 2 :(得分:0)

@James Aylett向我指出了正确的路径,看来我的问题是subprocess.Popen在我调用.flush()时没有完成运行。

解决方法是在subprocess.Popen调用之后立即调用p.wait(),以允许底层命令完成。在这之后,.flush做正确的事(因为所有数据都在那里),我可以继续从文件中读取。

所以上面的代码变成了:

  myFile = open(fileName, "w")
  p = subprocess.Popen(args, stdout=myFile)

  p.wait()          # <-- Missing line

  myFile.flush()    # force the file to disk
  os.fsync(myFile)  # ..
  myFile.close()

  myFile = open(fileName, "r")
  while myFile.readline():
    pass # do stuff
  myFile.close()

然后一切正常!