Reset blender environment on each script run I'm building a model completely in python. This means that I start with an empty scene, and all I want to do is run a python command that creates all meshes and objects. I'm building this python script in vi, just because blender is amazing 3D software, but lousy at making a decent text editor.

Off topic: The main reason for building my model this way, is that I want to have complete control over what I build, complete reproducibility, and I get to store my model in github, having proper version control and clear change sets. I would certainly be interested in hearing some off-topic reactions on how I could do this better/differently.

While developing this script, I constantly want to reload, from scratch, change a line in my script, reload, etc. I was wondering what the best way to achieve this is. My requirements:


It has to be simple, a couple of keystrokes, since I'm doing this multiple times per minute.
I don't want to restart blender every time, just because it takes a couple of seconds to start blender, and because the blender window doesn't appear in the right spot by default (this latter is possibly fixable).
Preferably I start from a new state (as in: File -> new) or in a known saved state (File --> open). Between reruns I do things in the interface and I may accidentally alter some property without knowing it. Ideally this would be reset on the next run.
Preferably the execution is triggered by the Python Console, so that errors appear there (and not in the bash console used to start blender).


Things I've tried so far:

Loop over all objects and delete them

I can manually try to delete all objects (using the method described here): http://blenderscripting.blogspot.nl/2012/03/deleting-objects-from-scene.html
This doesn't quite work (it crashes if there are hidden objects), but this is probably solvable. However it doesn't satisfy my 3rd requirement. It does allow my to make 1 oneliner that loops over all objects, delete them, and then runs my script again.

Using bpy.ops.wm.read_homefile() to get to the new state

Using this command I can get to the new state, however this also resets the python console, meaning that any subsequent command gets ignored and I can't up-arrow anymore to get it back.

Use bpy.ops.wm.open_mainfile() to get to a known saved state

This suffers from the same problem as the previous bpy.ops.wm.read_homefile, however it allows me to save some history in the python console, so I can up-arrow to it. It works, sort of, but not ideal.

In all of the above settings, I used

exec(compile(open(filename).read(), filename, "exec"))

to execute the script.

My latest plan is to use modules (however I think it would work just as well with the above exec command), and the undo history. Calling operators from a script doesn't add them to the undo history, so if after the running of the script I push onto the undo stack, I can then cmd-Z my way to the previous state. I could probably. When I start, I run once (single is my module name):

import sys; import importlib; sys.path.append("/path/with/my/module"); import single;

Now I use the oneliner

importlib.reload(single); single.build_single((20,25,0)); bpy.ops.ed.undo_push()

whenever I want to see how my program runs. When I'm ready to do a new run, I cmd-Z until I'm back at the beginning (most of the time once, sometimes I did some manual operations and need to press it more often).

Somehow I feel however that there must be a better way to do this, to reset the scene to some saved or new state, while the python script keeps running....

EDIT 2015-5-5

I still haven't found a good solution to this problem. However since all I really needed was to make relatively simple 3D objects for printing on my 3D printer and sending of to Shapeways, I found OpenSCAD more suitable, and 100% text based, which allows me easy checkins into git and changesets. Don't get me wrong, I think Blender is the tool for amazing 3D rendered images and animations, for my use however it was overkill.
I fear that this can only give a partial answer.

I wrote an add-on (totally work in progress..but whatever) which gives the python console in Blender a second function. Hitting Enter, executes normal python stuff, but I can type commands and hit Cltr+Enter and the add-on will read the current line and parse it and react to it. One command I do tend to use a lot is wipe it removes all objects/meshes, the code for it is pretty much:

    elif m == 'wipe':
        remove_obj_and_mesh(context)
        add_scrollback('wiped objects and meshes', 'OUTPUT')
        # history_append(text=m, current_character=0, remove_duplicates=True)
        history_append(text=m, remove_duplicates=True)


This even prints the message 'wiped objects and meshes' in blue to the Python console

The code for remove_obj_and_mesh() is:

def remove_obj_and_mesh(context):
    scene = context.scene
    objs = bpy.data.objects
    meshes = bpy.data.meshes
    for obj in objs:
        if obj.type == 'MESH':
            scene.objects.unlink(obj)
            objs.remove(obj)
    for mesh in meshes:
        meshes.remove(mesh)


 

I've not tested that on hidden objects, but if you can link a representative file / blend state which you would like to wipe entirely or selectively, i recommend posting it and that will let us/me answer more concisely.

ps. blenderscripting.blogspot is my blog, i should probably change that code