在Python模块中存储JSON数据的最佳方法

5
我正在开发一个Python模块,其中包括一个重要的JSON文件作为其所依赖的数据的一部分。我希望Python用户能够将JSON文件导入为Python变量,并且其他编程语言的用户也能够直接使用JSON文件。
因此,我试图找出最佳方法使JSON对象“可导入”。目前,我的解决方案在__init__.py中:
import json
import os

with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'seals.json')) as f:
    seals_data = json.load(f)

然后Python开发人员可以调用:
from my_module import seals_data

它或多或少可以工作,但这对我来说感觉很奇怪,我想确保没有更清晰的方法使json可导入。


1
你的解决方案看起来很适合你想要实现的目标。但是为什么他们不能自己做json.load呢?我觉得这样会使问题变得过于复杂化。 - Kiarash
1
这几乎就是我使用的代码。我将模块加载为单例。 - ldgabbay
@Kiarash,将其作为Python模块的优点是用户可以导入它,而不管模块安装在哪里。使用json文件时,代码必须知道它的位置才能进行“加载”。 - mlissner
@ldgabbay,你能解释一下如何实现单例模式吗? - mlissner
@mlissner,Python 只会在模块中运行一次代码。通过导入解析文件的代码,任何在第一次调用后导入该模块的人都会得到已经解析的结果(seals_data)。此外,如果没有人导入该模块,则文件永远不会被解析。因此,seals_data 是一个单例。 - ldgabbay
@ldgabbay,明白了,非常感谢。 - mlissner
1个回答

2
您的选项可能是将数据作为Python结构存储在模块中供其他人使用的最佳方法。唯一的缺点是导入该模块的任何内容都必须等待它进行IO,这并不理想,特别是如果该模块用于不涉及该数据的事情。我建议使用类或函数来延迟加载数据,从而只在请求该数据时才进行IO操作。
以下是一个示例:
SEALS_DATA = None
def get_seals_data():
    global SEALS_DATA
    if SEALS_DATA is None:
        SEALS_DATA = json.load(open("%s/seals.json"%(os.path.dirname(__file__))))
    return SEALS_DATA

在导入模块后,直到第一次调用 get_seals_data(),他们将没有交易。之后的任何调用都应该已经加载了数据。

嗯,在导入期间的IO并不那么糟糕。我几乎宁愿在代码执行的某个随机部分进行IO,也不想要这种情况。不确定这是否值得额外的复杂性和全局变量。 - mlissner
1
是的,这真的取决于是否会有不需要 JSON 对象的东西导入此模块。如果模块所做的全部工作就是提供 JSON 对象,那么你可以假设除非有人需要它,否则没有人会导入它。 - Luke Wahlmeier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接