What is a good solution to store a json data in the code? I am carrying out a project that requires a json file, which is automatically downloaded when Blender starts.
This json file contains a list of internet sites, and I wish I could populate a series of buttons in the menu.
The fundamental problem is that I would only like to load the json file once I find it, but I don't know where to store it.
The script works like this (approx.):
File my_json.json:
 {
     &quot;site_list&quot;:{&quot;Stackexchange&quot;:&quot;https://blender.stackexchange.com/&quot;,
                  &quot;Google&quot;:&quot;https://google.com/&quot;}    
 }

Code:
import bpy,json,os,webbrowser
from bpy.props import StringProperty


def open_json():
    json_file = &quot;G:\\my_json.json&quot;
    f = open(json_file) 
    data = json.load(f)  
    f.close()
    return data


class HelloWorldPanel(bpy.types.Panel):
    &quot;&quot;&quot;Creates a Panel in the Object properties window&quot;&quot;&quot;
    bl_label = &quot;Hello World Panel&quot;
    bl_idname = &quot;OBJECT_PT_hello&quot;
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = &quot;object&quot;

    def draw(self, context):
        layout = self.layout
        col=layout.column()
        
        
        data = open_json()
        for site , adress in data['site_list'].items():
            col.operator(&quot;object.simple_operator&quot;,text = site).options = adress #I pass a string to the operator (Web address)
        
        
        
class SimpleOperator(bpy.types.Operator):
    &quot;&quot;&quot;Tooltip&quot;&quot;&quot;
    bl_idname = &quot;object.simple_operator&quot;
    bl_label = &quot;Simple Object Operator&quot;
    
    options: StringProperty()

    def execute(self, context):
        
        webbrowser.open(self.options) #Open web adress in the default browser

        return {'FINISHED'}


def register():
    bpy.utils.register_class(SimpleOperator)
    bpy.utils.register_class(HelloWorldPanel)

def unregister():
    bpy.utils.unregister_class(SimpleOperator)
    bpy.utils.unregister_class(HelloWorldPanel)


if __name__ == &quot;__main__&quot;:
    register()

Result:

This method works, but the problem is that it iterates over and over to the Json file, opens it, reads it, closes it, and returns the data contained in it in the function return.
I was wondering where I could store this data, one time only. Read the file once, not read it again, and store the data somewhere.
Only layout in the draw method.
Every time the UI is redrawn a new panel class is instanced and its draw method called. Hence the excessive number of reads.
If the data is not changing then can read once when the module is imported, or when registered.
Have added an example of reading the data in operator definition ,making the data an enum property of the operator, and using a generic layout to expand the operator enum.
import bpy,json,os,webbrowser
from bpy.props import EnumProperty


def open_json():
    json_file = &quot;/home/batfinger/Desktop/json.json&quot;
    f = open(json_file) 
    data = json.load(f)  
    f.close()
    return data


class HelloWorldPanel(bpy.types.Panel):
    &quot;&quot;&quot;Creates a Panel in the Object properties window&quot;&quot;&quot;
    bl_label = &quot;Hello World Panel&quot;
    bl_idname = &quot;OBJECT_PT_hello&quot;
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = &quot;object&quot;

    def draw(self, context):
        layout = self.layout
        col=layout.column()
        col.operator_menu_enum(&quot;object.simple_operator&quot;, &quot;site&quot;)
        
        
        
class SimpleOperator(bpy.types.Operator):
    &quot;&quot;&quot;Tooltip&quot;&quot;&quot;
    bl_idname = &quot;object.simple_operator&quot;
    bl_label = &quot;Simple Object Operator&quot;
    data = open_json()['site_list']
    site: EnumProperty(
        items = [(site, site, address)
            for site, address in data.items()],
        name=&quot;Site&quot;,
        )
        
    def execute(self, context):
        
        webbrowser.open(self.data[self.site]) #Open web adress in the default browser

        return {'FINISHED'}


def register():
    bpy.utils.register_class(SimpleOperator)
    bpy.utils.register_class(HelloWorldPanel)

def unregister():
    bpy.utils.unregister_class(SimpleOperator)
    bpy.utils.unregister_class(HelloWorldPanel)


if __name__ == &quot;__main__&quot;:
    register()


Example of layout using
        col.operator_enum(
            &quot;object.simple_operator&quot;, 
            &quot;site&quot;)

If you are going to be using the data a lot would consider moving all the json in a separate module and expose the data on import.
from my_json_data import data