我正在使用 Raspberry PI 并使用 python 脚本从声音传感器输出值。为了显示这一点,我在 PI 上使用了一个 HTML 页面,该页面调用了一个 javascript include,它只是定义了一个值的一行,该值将用于更改 Google 仪表显示的内容。所有这些都非常简单明了,并且可以很好地满足我的需求。 (额外的好处是我真正了解它是如何工作的。)
.js 文件是由我的 python 脚本编写的,该脚本还执行许多其他操作。这一切实际上完全按照我想要的方式工作,并且写入文件的值是准确的,并且如果我将其作为单个循环运行而不是在其运行的连续“监视服务”模式下,则确实会正确显示在仪表上直到被中断。
我认为问题就从这里开始:测量声级的循环在 5 秒内运行了约 30k 次。在我的 python 代码中我使用:
with open(web_file, 'w') as f_output:
f_output.write("var int_level = " + str(per_detected))
f_output.close()
我这样做是因为我认为由于循环,我每次都需要关闭(我知道“with”是隐式关闭,但因为我每次都重新打开文件当然,似乎最好强制关闭它),但是我认为这也可能是问题所在。 (我还故意使用模式“w”,这样我每次都可以重置文件,因为它只是一行 - 似乎比替换值更快且计算成本更低)
症状是 Google 仪表 HTML 页面每 5 秒刷新一次以加载新值,但仪表本身可能每 10 次刷新才渲染一次,但这完全是随机的,显然表明仪表中没有值要返回的 .js 文件。我认为这意味着它可能会在几次尝试中幸运一次并在关闭之前击中文件,或者它是否太快而这是一种愚蠢的方法?
作为补充说明,当我从 PI 上的命令行 cat level.js (<- 包含文件)时,在“杀死”我的 python 代码之后,它是空的。
我的所有代码(包括 HTML 页面)位于:
https://www.GitHub.com/ChrisHarrold/Pi-Projects
如果您想查看更多详细信息。到周日为止,它有 6 种评论方式,所以弄清楚我做了什么以及为什么这样做应该很简单。
最佳答案
绝对不需要.close()
。问题是您的浏览器在文件仍然打开的情况下读取该文件,并且不时发现它处于 chop (如此空)的状态。而且您永远无法足够快地关闭文件来防止这种情况发生。
您应该做的是将文件写入不同文件名,然后重命名该文件以替换旧文件。这是一个原子操作(意味着操作系统保证对文件的任何其他访问都将获取旧文件或新文件,但绝不会只是两者的一部分)。
这很简单:
with open(web_file + '.new', 'w') as f_output:
f_output.write("var int_level = " + str(per_detected))
os.rename(web_file + '.new', web_file)
上面的代码写入不同的文件名,以.new
结尾,并且只有当写入完成(并且文件关闭)时,它才会移动到适当的位置以替换旧版本文件的内容。
关于javascript - Python file.close() 和 with() 在高频循环中的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39601070/