关于python:json.load()或json.dump()应该与open()上下文管理器一起使用吗?

Should json.load() or json.dump() be used with an open() context manager?

例如,假设我们正在检查一个preferences.json文件,其中包含

preferences.json

1
2
3
{
   "background_color":"red"
}

然后,我们使用python json模块读取/修改/写回首选项。以下两个示例的功能相同,除了一个使用open()上下文管理器,另一个不使用。

change_pref_with_CM.py

1
2
3
4
5
6
7
8
9
10
11
12
13
import json

# Load the user preferences
with open('preferences.json') as prefs_file:
    prefs = json.load(prefs_file)

print(prefs['background_color'])  # Prints 'red'
# Change the user's background_color preference to blue
prefs['background_color'] = 'blue'

# Save the user preferences
with open('preferences.json', 'w') as prefs_file:
    json.dump(prefs, prefs_file)

change_pref_without_CM.py

1
2
3
4
5
6
7
8
9
10
11
import json

# Load the user preferences
prefs = json.load(open('preferences.json'))

print(prefs['background_color'])  # Prints 'red'
# Change the user's background_color preference to blue
prefs['background_color'] = 'blue'

# Save the user preferences
prefs = json.dump(prefs, open('preferences.json', 'w'))

对于正常的文件读/写,我总是使用上下文管理器并处理上下文管理器内的所有逻辑。但在本例中,文件的使用时间刚好足以填充dict或将dict写入文件。所以不使用上下文管理器的例子对我来说似乎更清楚。我担心,由于这些文件是以"匿名"方式打开的,所以没有什么可以调用close()on的,我不知道JSON模块是否在内部使用上下文管理器来处理这些问题,或者我是否只是在泄漏文件描述符。我确信使用上下文管理器是一种安全的方式,但同时我想知道JSON模块如何处理文件描述符(或者它是文件对象?)

我开始寻找JSON模块的源代码,但是在找到它并搜索"dump"和"load"之后,我不知道接下来要检查什么。我对C还不够精通,无法理解里面发生了什么。


这两者都是安全的,但是使用上下文管理器的版本是更好的实践。

请记住,当您的程序退出时,所有写操作都将被刷新。也就是说,上下文管理器会导致立即关闭和刷新,而不是在垃圾收集上,也不是在退出时。因此,它更加明确,即使在程序末尾添加了更多(可能是长时间运行的)代码,也会确保事情立即生效。

也就是说,考虑一下让你的文章真正具有原子性。

这里仍然有一个窗口,文件已被打开以供输出,但没有新的内容被刷新;如果电源被猛拉,或者您有一个sigkill,或者读卡器试图将文件的内容拉入该窗口,您将丢失数据。请看用python编写原子文件;就我个人而言,我赞成@vog的建议,使用一个专门构建的库,它了解各种平台的习惯用法和最佳实践。