# Opening a blender file during python script execution without changing context

During execution of a python script, I'm trying to import a .blend file. It's currently not an option to load the file when Blender boots, although ideally we would get the same result either way. I'm using:

bpy.ops.wm.open_mainfile(filepath=path)


However, this destroys bpy.context ({.window, .screen} = None), but only when blender is started without "--background". This is the relevant Blender source code (blender/windowmanager/intern/wm_files.c):

if (!G.background) {
/* in background mode this makes it hard to load
* a blend file and do anything since the screen
* won't be set to a valid value again */
CTX_wm_window_set(C, NULL); /* exits queues */
}


This causes "invalid context" problems for different operators (e.g., bpy.ops.transform.*) called afterwards.

It would be great to be able to open .blend files without the WM/GUI interference altogether. However, since there doesn't seem to be a WM-less Python call for now, restoring the original context (or at least a context equivalent to the one when Blender starts up) would also work. Bonus points for solutions without WM hacks (e.g. simulating clicks) ;-)

• Do you run Blender in background mode or not? – CodeManX Aug 12 '14 at 20:04
• In our live environment we do, so there it's no problem, but for developing and testing we run without --background to see what happens. – Turiphro Aug 13 '14 at 8:09
• In fact, the purpose of importing a .blend file here is to import predefined objects + (Cycles) materials & lights. While everything works fine for Blender render with other file formats, .blend seems to be the only one able to export+import Cycles materials. Another way of importing Cycles-compatible scenes (without the bloated .blend file import) is also welcome. – Turiphro Aug 13 '14 at 8:13

Found a WM hack based on this answer that seems to work. Some operators still complain about "PyContext 'blend_data' not found", but this doesn't seem to result in problems so far. Still feels a bit hacky though.

def fix_context():
"""Fix bpy.context if some command (like .blend import) changed/emptied it"""
for window in bpy.context.window_manager.windows:
screen = window.screen
for area in screen.areas:
if area.type == 'VIEW_3D':
for region in area.regions:
if region.type == 'WINDOW':
override = {'window': window, 'screen': screen, 'area': area, 'region': region}
bpy.ops.screen.screen_full_area(override)
break


Edit: this works (with --background) but only if there's running an X server for the current user. Feels like there's some gui hacking going around when Blender python scripts are running background... Running on an X-less server gives a segfault.

• Background mode is actually just hiding the interface, though it is still required to hold necessary data, which is used by operators etc. I'm pretty sure you can just set bpy.context.area.type = 'VIEW_3D' to avoid context overriding, which should slim down your code a lot. – CodeManX Aug 27 '14 at 13:33
• This crashes 2.80 – yarun can Mar 13 '19 at 7:04