Can I perform an action when a file is saved or loaded? If I create a Blender file with a single plane that has 10&thinsp;000 particles of hair, the resulting file size is 9.9&nbsp;MB.

If, before saving, I reduce the "Number" (RNA ParticleSettings.count) to 1, the resulting file size is only 435&nbsp;KB.

Because the hair is randomly generated with a specified seed (ParticleSystem.seed), I can open the 435&nbsp;KB-file and set the number back to 10&thinsp;000 and get the exact same hair system generated.

In scenes where I have a lot of hair (especially grass, which can require millions of particles), I've seen differences as high as 50&nbsp;MB. Taking into account the two backup files, that's 150&nbsp;MB of disk (and, for me, cloud) space saved, which is a clear advantage. The downsides of this method, however, include:


It's cumbersome. I don't want to have to remember to disable something before saving and re-enable it when I load.
It's error-prone. I find myself adding README.txt files to my directories indicating the desired number of particles for each object, because otherwise I forget and my renders are inconsistent (all of a sudden the grass doubles).
It's forgettable. I've lost days of render time due to rendering a scene with a single grass particle because I've forgotten to reset the number. Obviously this is a human error problem, but it's not helped by Blender.


Is there a way I can attach a "save hook" and "open hook" to a file to do this automatically for me? I could easily write a Python script with custom settings for each particle system:

import bpy

def hair_reduce():
    for ps in bpy.data.particles:
        if ps.type == 'HAIR' and not 'actual_hair_count' in ps:
            ps['actual_hair_count'] = ps.count
            ps.count = 1

def hair_apply():
    for ps in bpy.data.particles:
        if ps.type == 'HAIR' and 'actual_hair_count' in ps:
            ps.count = int(ps['actual_hair_count'])
            del ps['actual_hair_count']


The trick, however, is to have these functions called when the file is saved or loaded.

Can I attach a save/load hook to Blender, or otherwise perform an action when the file is saved or loaded?
We can register handlers that will be executed before, or after, specific operations. The handler lists are all in bpy.app.handlers, and looking at your requirement, the handler list to use is save_pre (executed before saving) and load_post (executed after loading).

The function needs to be persistent, so they won't disappear every time a new file is loaded. Here's an example of how to register it, edited from my own addon needing such feature:

import bpy
from bpy.app.handlers import persistent

@persistent
def hair_reduce(dummy):
    print('hair_reduce')

@persistent
def hair_apply(dummy):
    print('hair_apply')

def register():
    if not hair_apply in bpy.app.handlers.load_post:
        bpy.app.handlers.load_post.append(hair_apply)
    if not hair_reduce in bpy.app.handlers.save_pre:
        bpy.app.handlers.save_pre.append(hair_reduce)

def unregister():
    if hair_apply in bpy.app.handlers.load_post:
        bpy.app.handlers.load_post.remove(hair_apply)
    if hair_reduce in bpy.app.handlers.save_pre:
        bpy.app.handlers.save_pre.remove(hair_reduce)