Skip to main content
4 of 4
added 809 characters in body
spacer
  • 921
  • 8
  • 22

How to bring the context "back" after running read_homefile()?

When I run

import bpy
bpy.ops.wm.read_homefile()

and then I replace the above with this (in the same text data block)

import bpy
rrr = bpy.ops.object.select_all(action='SELECT')
print("select_all result:", rrr)
print(">>>>>>>>>> bpy.context:", bpy.context)
print(">>>>>>>>>> bpy.context.object:", bpy.context.object)
print(">>>>>>>>>> bpy.context.object.name:", bpy.context.object.name)

and run it, I get this

select_all result: {'FINISHED'}
>>>>>>>>>> bpy.context: <bpy_struct, Context at 0x000000EEA420B5C8>
>>>>>>>>>> bpy.context.object: <bpy_struct, Object("Cube")>
>>>>>>>>>> bpy.context.object.name: Cube

However, when I run this (same code but merged)

import bpy
bpy.ops.wm.read_homefile()
rrr = bpy.ops.object.select_all(action='SELECT')
print("select_all result:", rrr)
print(">>>>>>>>>> bpy.context:", bpy.context)
print(">>>>>>>>>> bpy.context.object:", bpy.context.object)
print(">>>>>>>>>> bpy.context.object.name:", bpy.context.object.name)

I get this

select_all result: {'PASS_THROUGH'}
>>>>>>>>>> bpy.context: <bpy_struct, Context at 0x000000EEA420B5C8>
Traceback (most recent call last):
  File "\Text", line 7, in <module>
AttributeError: 'Context' object has no attribute 'object'

Why does that happen?

Is there a way to make the code after bpy.ops.wm.read_homefile() work "normally"?

Edit:
It seems that bpy.ops.wm.read_homefile() effectively "clears" the context - the bpy.context.area is None.

So the new question is how to bring the context back to the correct area?

Edit 2: I have found a workaround that searches for 3D View area and makes it current context - and here is the dubious part - by calling bpy.ops.screen.screen_full_area():

import bpy
bpy.ops.wm.read_homefile()
havesetthecontext = False
for window in bpy.context.window_manager.windows:
    screen = window.screen
    for area in screen.areas:
        print("area=", area)
        if area.type == 'VIEW_3D':
            override = {'window': window, 'screen': screen, 'area': area}
            bpy.ops.screen.screen_full_area(override)   # toggle to maximize
            bpy.ops.screen.screen_full_area()           # toggle back (must not use overridden context, else it will crash!)
            havesetthecontext = True
            break

if havesetthecontext:
    rrr = bpy.ops.object.select_all(action='DESELECT')
    print("select_all result:", rrr)
    print(">>>>>>>>>> bpy.context:", bpy.context)
    print(">>>>>>>>>> bpy.context.object:", bpy.context.object)
    print(">>>>>>>>>> bpy.context.object.name:", bpy.context.object.name)
else:
    print("Could not set the context to 3D View!")

Now, isn't there a way to set a context directly, something like bpy.context.set(override)?

Edit 3:
The above workaround is unstable (occasionally crashes Blender) unless Load UI is disabled.
So, add this line before calling bpy.ops.wm.read_homefile():

bpy.context.user_preferences.filepaths.use_load_ui = False

That, of course, kind of kills the purpose of reloading startup file, unfortunately.

Oh, and the same issues appear when calling read_factory_settings().

When I run the screen_full_area() stuff from load_handler then it does not crash, however, in the "main" code the bpy.context.area is still None - and when I do screen_full_area() stuff there too, it crashes again.

I suspect that crashing is due to some code in screen_full_area(), not the context changing, so we are back to the question is there a way to set the context directly?

spacer
  • 921
  • 8
  • 22