From Blender Developer Wiki
Jump to: navigation, search

Updating Scripts from 2.7x

This page lists change you may need to make to your scripts so they run in 2.8x.

Please note: The current Python API for Blender 2.8 is under active development and considered unstable (it may change at any time). It is generally recommended add-on authors wait until after the 2.8 Beta is released (planned for late October) to update their code.

Version Info

Make sure the "blender" key in the bl_info dictionary is set to (2, 80, 0) not (2, 8, 0) or (2, 79, 0)

Example: "blender": (2, 80, 0),

Otherwise, this error is reported:

Exception: Add-on 'ADDON_NAME' has not been upgraded to 2.8, ignoring

Module Registration

Module registration (bpy.utils.register_module) convenience function has been removed, since keeping track of this information adds unnecessary overhead.

Add-on's should assign their classes to a tuple or list and register/unregister them directly.


classes = (

def register():
    from bpy.utils import register_class
    for cls in classes:

def unregister():
    from bpy.utils import unregister_class
    for cls in reversed(classes):

To avoid having to copy & paste the functions above, you can use bpy.utils.register_classes_factory utility function.

classes = (
register, unregister = bpy.utils.register_classes_factory(classes)

If you have an addon with many classes, the list can be generated using this patch:

Class Registration

See T52599 for proposal and details.

Access (bpy.types)

Now only [Header, Menu, Operator, Panel, UIList] are accessed from bpy.types.

Generally scripts access classes they define by importing their own modules, so this should not impact many scripts.


In Blender2.7x it was too easy to accidentally register multiple classes with the same name.

To prevent collisions 2.8x enforces naming conventions (already in use across much of Blender's code-base)

This constraint applies to the bl_idname of each class (or the class name which is used if no bl_idname is defined in the class).

These are: UPPER_CASE_{SEPARATOR}_mixed_case, in the case of a menu the regular expression is:


Each classes separator is listed below:

  • Header -> _HT_
  • Menu -> _MT_
  • Operator -> _OT_
  • Panel -> _PT_
  • UIList -> _UL_

Valid Examples:

  • OBJECT_OT_fancy_tool
  • SOME_HEADER_HT_my_header
  • PANEL123_PT_myPanel (lower case is preferred but mixed case is supported).

At time of writing names that don't conform to this convention will warn on startup. Eventually we will make this into an error, eg:

Warning: 'Oscurart Files Tools' doesn't contain '_PT_' with prefix & suffix
Warning: 'Oscurart Overrides' doesn't contain '_PT_' with prefix & suffix
Warning: 'Oscurart Animation Tools' doesn't contain '_PT_' with prefix & suffix

Class Property Registration

Classes that contain properties from `bpy.props` now use Python "fields",


class MyOperator(Operator):
    value = IntProperty()


class MyOperator(Operator):
    value: IntProperty()

Using the 2.7x syntax in 2.8 will result in this error:

Warning: class Foo "contains a properties which should be a field!"

Matrix Multiplication

Matrix multiplication previously used *, scripts should now use @ for multiplication (per PEP 465). This applies to:

  • Vector * Vector
  • Quaternion * Vector
  • Matrix * Vector
  • Vector * Matrix
  • Matrix * Matrix

Note: In future * will be used for element-wise multiplication


mat = Matrix()
vec = Vector()
result = mat * vec


mat = Matrix()
vec = Vector()
result = mat @ vec

Using the 2.7x syntax in 2.8 will result in this error:

TypeError: Element-wise multiplication: not supported between 'xxx' and 'yyy' types

Noise Module

Noise and Metric Enumerators

Enumerators in 2.7x were implemented as module level constants. These have been changed to string enumerators:


noise.noise(position, noise_basis=noise.types.BLENDER)


noise.noise(position, noise_basis='BLENDER')

Keyword Only Arguments

All keyword arguments must be given as keywords and cannot be passed by position:


noise.noise(position, noise.types.BLENDER)


noise.noise(position, noise_basis='BLENDER')

Noise Type Naming

When transitioning to string enumerators, the following transitions apply:

noise.types.BLENDER         -> 'BLENDER'
noise.types.STDPERLIN       -> 'PERLIN_ORIGINAL'
noise.types.NEWPERLIN       -> 'PERLIN_NEW'
noise.types.VORONOI_F1      -> 'VORONOI_F1'
noise.types.VORONOI_F2      -> 'VORONOI_F2'
noise.types.VORONOI_F3      -> 'VORONOI_F3'
noise.types.VORONOI_F4      -> 'VORONOI_F4'
noise.types.VORONOI_F2F1    -> 'VORONOI_F2F1'
noise.types.CELLNOISE       -> 'CELLNOISE'

BMesh Operator Enumerators and Flags

BMesh operator enumerators/flags in 2.7x were integer arguments. In 2.8x this has been changed to string enumerators:


bmesh.ops.mirror(bm, geom=verts, axis=1)


bmesh.ops.mirror(bm, geom=verts, axis='Y')

Scene Layer Access


Object Selection Access


Blender 2.8 New Python API Features

Skin Root Vertices Settable

Mesh skin vertex roots can now be set through the API.

l =
v = bm.verts[0]
v[l].use_root = True

Note: Each mesh island should only have one root vertex, however it is up to script writer to ensure this is the case.