Accessing screen areas from render handler The code below works flawless, if e.g. triggered by a menu button in a 3D view.

        for area in bpy.context.screen.areas: 
          if area.type == 'VIEW_3D':
            for space in area.spaces:
                if space.type == 'VIEW_3D': 
                    space.viewport_shade = 'BOUNDBOX'


However, if I bundle it into a function and hook it to a handler, it returns a NoneType error:

@persistent
def allBound(dummy):
  for area in bpy.context.screen.areas: 
      if area.type == 'VIEW_3D':
        for space in area.spaces:
            if space.type == 'VIEW_3D': 
                space.viewport_shade = 'BOUNDBOX'

 bpy.app.handlers.render_pre.append(allBound)


Returns:

AttributeError: 'NoneType' object has no attribute 'areas'


How to solve this?
Turns out that inside bpy.app.handlers.render_pre the context is different.

For example bpy.context.screen is None, bpy.context has no attribute active_object etc. Looks like its very limited when rendering.

What you have access to is bpy.context.window_manager. So modify your script like this and it should work:

import bpy

def allBound(scene):
    for window in bpy.context.window_manager.windows:
        for area in window.screen.areas: 
            if area.type == 'VIEW_3D':
                for space in area.spaces:
                    if space.type == 'VIEW_3D':
                        space.viewport_shade = 'BOUNDBOX'

bpy.app.handlers.render_pre.append(allBound)


Also this now works on a multi-monitor layout.