I have noticed that when creating addon, if the bl_info is create with variable. The script will break the addon system. Causing disappear tab after restarting blender:

desc = 'Run script in any space with given name of script'
import bpy

bl_info = {
    "name": "Run specified script in all context",
    "description": desc,  # Here, a variable. (And WTF is this code highlight?)
    "author": "hikariTW",
    "version": (0, 1, 0),
    "blender": (2, 80, 0),
    "location": "TextEditor",
    "support": "TESTING",
    "category": "Interface",

enter image description here

Is there any workaround or this is normal when dealing with static examine of script when Blender try to list them out?

The test is done in Blender 2.83.4

Further testing which also break addon:

  • f-string and str.format
  • formatting with const-like 15 'foobar' without variable.
  • Conditional Expression: "foo" if True else "bar"
  • $\begingroup$ Have you tried "description" : f"{desc}", ? $\endgroup$
    – Gorgious
    Commented Sep 25, 2020 at 7:44
  • $\begingroup$ Nope, any string format with any kind of variable even pure int or str. Including f"{desc}" and "{}".format(150). It seems that it need to be pure text formatting without any statement. $\endgroup$
    – HikariTW
    Commented Sep 25, 2020 at 7:53
  • $\begingroup$ Oh, alright. Are you dynamically pulling the description from another file / module or is it for a translation ? $\endgroup$
    – Gorgious
    Commented Sep 25, 2020 at 7:55
  • $\begingroup$ Just simply want to separate code into different part for better formatting. $\endgroup$
    – HikariTW
    Commented Sep 25, 2020 at 8:00

3 Answers 3



Sure this is a dupe, have searched and searched,

For want of a better reference


bl_info must be declared in the module.

This is because bl_info is extracted without executing code.

ie the bl_info dictionary is grepped out of the addon module top level file (foo.py or foo/__init__.py) as a string where the locals will not be available.

  • $\begingroup$ Thanks for the link, but shouldn't Blender handle the exception carefully and indicate that there is some invalid bl_info rather that just failed to fetch data and make whole addon panel failed? $\endgroup$
    – HikariTW
    Commented Sep 25, 2020 at 8:29
  • 1
    $\begingroup$ Wish I could find when this was previously asked as IIRC it was well explained, on how the dictionaries are used to build the fake modules list. Yep could add some exception handling for this..... yet again the addons panel can already be a ponderously slow beast. Adding an exception test for something that as demonstrated doesn't work, is fixed by not doing it. $\endgroup$
    – batFINGER
    Commented Sep 25, 2020 at 8:34
  • $\begingroup$ .. have my nose in dynamically creating addons. The concept of having a single tools umbrella addon has kinda taken a big hit with the association of addons with workspaces, and currently end up with all or nothing. Might write a q re this one day. $\endgroup$
    – batFINGER
    Commented Sep 25, 2020 at 8:44
  • $\begingroup$ @batFINGER - Do you happen to have a link where you discuss this idea of a "single tools umbrella addon?" It sounds immensely interesting as I was trying to make something along that line (if I understand correctly). $\endgroup$ Commented May 5 at 19:37

So it seems like Blender is using ast.literal_eval() for finding bl_info without execute whole addon content.

As the references said, using eval to evaluate arbitrary addon would be extremely dangerous. And the potential corrupt code will also make Blender vulnerable to malware.



This can be done with a workaround, especially if you develop externally and have an automated reload system like the amazing Blender Development VS Code extension created by Jacques Lucke.

As an example if using the above mentioned extension, you can create a "templating file" and have it write out your template to __init__.py, with whatever variables you want:

import datetime

timestomp = datetime.datetime.now().strftime('%y,%m%d,%H%M')
version = tuple(int(x) for x in timestomp.split(','))

text = f'''# AUTO GENERATED - do not edit if you value your time and/or sobriety
import bpy

bl_info = {{
    'name' : 'RenderNextSlot',
    'author' : 'Human McAuthor',
    'description' : 'Always render into a new render slot, instead of overwriting the current render slot.',
    'blender' : (4, 0, 1),
    'version' : {version},
    'location' : '',
    'warning' : '',
    'category' : 'Render'

from . import auto_load

def register():

def unregister():

with open('__init__.py', 'w') as f:

Now, every time you reload the add-on, the __init__.py file will be re-generated with your updated variables. If not using the extension, you just need to run your template code whenever you want your bl_info updated.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .