【问题标题】:Python refresh file from diskPython 从磁盘刷新文件
【发布时间】:2015-03-05 22:40:40
【问题描述】:

我有一个 python 脚本,它调用系统程序并从文件out.txt 读取输出,对该输出进行操作,然后循环。但是,它不起作用,仔细调查表明,python 脚本只打开一次out.txt,然后继续从那个旧副本中读取。如何让 python 脚本在每次迭代时重新读取文件?我在 SO 上看到了一个类似的问题,但它是关于一个与程序一起运行的 python 脚本,而不是调用它,并且解决方案不起作用。我尝试在循环返回之前关闭文件,但它没有做任何事情。

编辑: 我已经尝试关闭和打开,它没有工作。代码如下:

import subprocess, os, sys

filename = sys.argv[1]
file = open(filename,'r')
foo = open('foo','w')
foo.write(file.read().rstrip())
foo = open('foo','a')
crap = open(os.devnull,'wb')
numSolutions = 0

while True:
    subprocess.call(["minisat", "foo", "out"], stdout=crap,stderr=crap)
    out = open('out','r')
    if out.readline().rstrip() == "SAT":
        numSolutions += 1
        clause = out.readline().rstrip()
        clause = clause.split(" ")
        print clause
        clause = map(int,clause)
        clause = map(lambda x: -x,clause)
        output = ' '.join(map(lambda x: str(x),clause))
        print output
        foo.write('\n'+output)
        out.close()
    else:
        break

print "There are ", numSolutions, " solutions."

【问题讨论】:

  • 可以关闭再打开。
  • 你每次都写入文件吗?
  • 嘿,你还在吗?系统程序很可能会删除旧的out.txt 并写入一个新的。至少在 linux 上,打开的文件句柄将指向旧的未链接文件,并且永远不会看到新数据。由于关闭/打开是显而易见的解决方案,您能告诉我们它是否有效吗?
  • @tdelaney 它应该覆盖 out.txt。我正在使用 minisat 通过将旧解决方案乘以 -1 并将其附加到输入文件来计算 SAT 问题的解决方案数量。所以算法是minisat输入输出,将输出乘以-1,附加到输入,重复。问题是初始读取后输出不会改变。我确实在循环结束时将其关闭并重新打开,但它不起作用。我在我的问题中发布了代码。
  • 一些事情要尝试...在运行之前执行if os.path.isfile("out"): os.remove("out") 并临时将stdout 和err 传输到一个文件中,看看是否发生了其他一些坏事。

标签: python io


【解决方案1】:

您使用 file_var 并使用 file_var.close() 结束循环。

for ... :
    ga_file = open(out.txt, 'r')
    ... do stuff
    ga_file.close()

下面的实现演示(尽可能简单,这是所需的所有 Jython 代码)...

__author__ = ''
import time

var = 'false'
while var == 'false':
    out = open('out.txt', 'r')
    content = out.read()
    time.sleep(3)
    print content
    out.close()

产生这个输出:

2015-01-09, 'stuff added'
2015-01-09, 'stuff added'           # <-- this is when i just saved my update
2015-01-10, 'stuff added again :)'  # <-- my new output from file reads

我强烈建议阅读错误消息。他们拥有相当多的信息。

我认为应该为调试目的编写完整的文件名。

【讨论】:

  • os.path.join(path, filename) + '.skv' 是从哪里来的?
  • 抱歉,使用了项目中的示例代码。我认为代码现在更符合您的喜好;)
  • 你可以使用with open(out.txt) as ga_file:
  • 我认为最好的解决方案是让一个监听器在文档更新或创建时被调用。与此类似:stackoverflow.com/questions/9318581/… 这样循环仅在文件更新时运行,并且避免了不必要的 i/o。
  • @victor:你确定你提供的链接吗?引用的问题没有提及听众。
【解决方案2】:

我重写了它,希望它更容易理解:

import os
from shutil import copyfile
import subprocess
import sys

TEMP_CNF = "tmp.in"
TEMP_SOL = "tmp.out"
NULL = open(os.devnull, "wb")

def all_solutions(cnf_fname):
    """
    Given a file containing a set of constraints,
    generate all possible solutions.
    """
    # make a copy of original input file
    copyfile(cnf_fname, TEMP_CNF)

    while True:
        # run minisat to solve the constraint problem
        subprocess.call(["minisat", TEMP_CNF, TEMP_SOL], stdout=NULL,stderr=NULL)

        # look at the result
        with open(TEMP_SOL) as result:
            line = next(result)
            if line.startswith("SAT"):
                # Success - return solution
                line = next(result)
                solution = [int(i) for i in line.split()]
                yield solution
            else:
                # Failure - no more solutions possible
                break

        # disqualify found solution
        with open(TEMP_CNF, "a") as constraints:
            new_constraint = " ".join(str(-i) for i in sol)
            constraints.write("\n")
            constraints.write(new_constraint)

def main(cnf_fname):
    """
    Given a file containing a set of constraints,
    count the possible solutions.
    """
    count = sum(1 for i in all_solutions(cnf_fname))
    print("There are {} solutions.".format(count))

if __name__=="__main__":
    if len(sys.argv) == 2:
        main(sys.argv[1])
    else:
        print("Usage: {} cnf.in".format(sys.argv[0]))

【讨论】:

  • 谢谢!这非常有用。什么是shutil?
  • “Shell 实用程序”是一个标准库模块,包含用于复制、移动和重命名文件的有用功能。
【解决方案3】:

您需要刷新foo 以便外部程序可以看到它的最新更改。当您写入文件时,数据会在本地进程中缓冲并以更大的块发送到系统。这样做是因为更新系统文件相对昂贵。在您的情况下,您需要强制刷新数据,以便 minisat 可以看到它。

    foo.write('\n'+output)
    foo.flush()

【讨论】:

  • 你打错字了,minista应该是minisat
猜你喜欢
  • 2010-09-15
  • 2010-09-10
  • 1970-01-01
  • 1970-01-01
  • 2011-02-14
  • 2012-11-25
  • 1970-01-01
  • 1970-01-01
  • 2017-06-17
相关资源
最近更新 更多