34
$\begingroup$

I keep on getting context errors in the Blender Python API.

I don't understand the issue of the context in the API, how do I know which is the correct context?

Thanks!

$\endgroup$
46
$\begingroup$

The context members available depend on the area of blender which is currently being accessed.

See bpy.context

Many operators have a “poll” function which may check that the mouse is a valid area or that the object is in the correct mode (Edit Mode, Weight Paint etc). When an operator’s poll function fails within python, an exception is raised.

See Operator.poll()

More about using Operators and why you experience poll-fails (mouse not over right screen area or wrong mode / other pre-condition). Also see the Gotchas section of the API docs about that.

You can either:

  1. Run an operator via spacebar menu (see bottom of the section) in Blender 2.7x or using F3 as of Blender 2.8x from the proper Area (bl_options must not contain 'INTERNAL')
  2. Specify the right execution context for the operator call (this fixes the context error only for some!)
    (API docs, example)
  3. Use an override to pass the required context arguments
  4. Change the Area.type temporarily
  5. Use "low-level" API functions to achieve the same result without context worries

Override

Doesn't seem to work for this operator?! It adds a background but without name / texture.

import bpy
for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        override = bpy.context.copy()
        override['area'] = area
        bpy.ops.view3d.background_image_add(override, name="BG", filepath=r"image.png")
        break

By the way:
You can pass an empty dict (like bpy.ops.example.operator({})), which usually prints warnings to the system console about the context members missing. You need to pass these members and repeat until it doesn't complain anymore. But beware of certain operators, which require scene bases - if you don't provide a reference to them, Blender will crash to desktop before you even find out they are needed.

Change Area.type

area = bpy.context.area
old_type = area.type
area.type = 'VIEW_3D'
bpy.ops.view3d.background_image_add(name="BG", filepath=r"image.png")
area.type = old_type

Low-level

Similar to the override, you need a 3D View instance, in this case its space data (because this is the place where backgrounds reside). The following code takes the first 3D View of the current screen layout (if there's one), adds a new background and sets the image to an image datablock:

import bpy

filepath = r"C:\path\to\image.png"

img = bpy.data.images.load(filepath)

for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        space_data = area.spaces.active
        bg = space_data.background_images.new()
        bg.image = img
        break
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.