bpy.ops.preferences.addon_enable() only checks for changes in __init__.py; Problem for multi-file add-ons #66924
Labels
No Label
Interest
Animation & Rigging
Interest
Blender Cloud
Interest
Collada
Interest
Core
Interest
Documentation
Interest
Eevee & Viewport
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
Import and Export
Interest
Modeling
Interest
Modifiers
Interest
Nodes & Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds, Tests & Devices
Interest
Python API
Interest
Rendering & Cycles
Interest
Sculpt, Paint & Texture
Interest
Translations
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Meta
Good First Issue
Meta
Papercut
Module
Add-ons (BF-Blender)
Module
Add-ons (Community)
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
8 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender-addons#66924
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Symptoms
When you're developing an add-on existing out of multiple files on a disk, you want to reload your add-on many times to include the changes you made.
This works fine when you make a modification in
__init__.py
and callbpy.ops.preferences.addon_enable(module='your_module')
, as you will see:"module changed on disk: 'path/to/file.py' reloading..."
.However, if you make a change in another module, e.g.
your_module_props.py
, and calladdon_enable()
, nothing is triggered. You will only see{'FINISHED'}
.If you afterwards make a change to
__init__.py
, the previous changes you made toyour_module_props.py
are seen by Blender this time when you calladdon_enable()
.Likely culprit
I believe the culprit is here: https://developer.blender.org/diffusion/B/browse/master/release/scripts/modules/addon_utils.py$325
These lines of code only check if the main file (
__init__.py
) has changed.Possible solutions
One of the following:
Importance
Any medium/large add-on that follows proper code conventions to prevent spaghetti code will use multiple files. This limited check to only
__init__.py
severely slows down app development, as we cannot do a quick reload. Instead we have to make a minimal change to__init__.py
to trigger the reload, or restart Blender every time we have made a code modification.Added subscriber: @NumesSanguis-3
To test if the check
if mtime_orig != mtime_new:
is indeed the problem, I made an operator (simplified version of the originaladdon_enable()
: developer.blender.org/diffusion/B/browse/master/release/scripts/modules/addon_utils.py$327) with that removed:and indeed, the add-on properly reloads now.
So I would suggest solution 2 in the main post.
Added subscriber: @dr.sybren
Changed status from 'Open' to: 'Archived'
Fortunately, this is not as big an issue as you describe. The code you linked is only used when enabling an add-on; the issue you describe seems to assume the way to reload an add-on is to disable and enable it.
Reloading your add-on can be done via the
bpy.ops.script.reload()
operator which was bound to F8 in Blender 2.79; it's now available with the F3 menu (search for 'reload scripts') and you can create your own keyboard binding if you want. Multi-file addons need reloading support, which is quite easy to do; see this slide and the following slides or watch my Blender Conference 2016 workshop on the subject.Thank you @dr.sybren ,
bpy.ops.script.reload()
indeed reloads all add-ons. I hadif "bpy" in locals():
check to reload add-ons, but that wasn't triggered by my code, because__init__.py
didn't change.While luckily indeed a smaller issue than I assumed, I think it's nota solved one.
bpy.ops.script.reload()
instead ofbpy.ops.preferences.addon_enable(module='your_module')
I would assume the most knowledgeable Python programmers are active here, and therefore it seemsbpy.ops.script.reload()
is not common knowledge. This is more a documentation issue, so I created an issue about this here: https:*developer.blender.org/T67387bpy.ops.script.reload()
reloads ALL add-ons. If one of these add-ons is producing a error / warning, it will pollute the output/logs for the add-on you're actually try to develop. Also, if (multiple) non-relevant add-on(s) are slow at initializing, it will slow down the development process. Possible solutions I could think of:bpy.ops.script.reload(module_name=None)
, and only reload all when either None or no argument is passed.bpy.ops.preferences.addon_enable(module='your_module')
intended for reloading specific add-ons by remove / extend the check if only__init__.py
file changed.Added subscriber: @ideasman42
For development, you can:
Checking the date on the init file isn't meant to be a comprehensive check of the entire package.
Not all of them, and not all the time. Just search the Python API documentation for "reload script" and you'll find the
bpy.ops.script.reload()
operator. Granted, it's not documented very well.Well, if you keep multiple non-relevant add-ons enabled while you're developing, I don't think this is an issue with reloading. I think it's an issue between keyboard & chair.
You could even add this code to an operator in your add-on and bind it to a menu item or button, then it's literally a one-click reload for only your add-on.
Added subscriber: @geckoman
I have created a workaround to this problem.
Example init.py:
someclass
andsomemodule
will stay up-to-date when reloading addon withbpy.ops.preferences.addon_enable()
and withbpy.ops.script.reload()
.Don't use the
from X import Y
syntax to import individual classes, that'll make reloading more cumbersome (as you've seen). If you just import (sub)modules you avoid the need for thatreload_class()
function.That's good advice. I've gotten so used to just Googling things and usually finding the answer on stackoverflow, I forgot about direct searching.
For some reason Google doesn't index the Blender documentation, which would probably trouble more newcomers to Blender.
While in most case you'd be right, there are people who develop add-ons, that rely on / add functionality to add-ons of others. It is not always possible to merge this into 2 add-ons.
You could say, you could help speed-up that add-on, but some add-on creators are satisfied with their solution of whatever reason they have to not accept your contribution.
Also, it's possible that the add-on you rely on is good, but only requires a long initialization time (e.g. setup TCP connections to programs outside Blender, not so weird if you want to visualize data from a Robot).
The situation at the moment is:
bpy.ops.preferences.addon_enable(module='your_module')
)bpy.ops.script.reload()
)Is it a huge problem? Not really. However, to me it feels like poor design that you can't just reload 1 add-on. Even if in most cases reloading all add-ons won't be much of a slowdown.
Would you say it makes sense if there is a function that can reload a (list of) specific add-ons? Given it's not too much effort to implement.
p.s. Could someone point me to the reload script?
importlib
doesn't find me anything on https://developer.blender.org/diffusion/B/browse/master/site:https://developer.blender.org/ importlib
doesn't show up anything either.p.p.s
Asked for referencing the code by making the function names on the documentation page clickable: https://developer.blender.org/T67674
Yeah, I did this. Is slightly less smooth if you're bugs are in the registering of the modules, which breaks the unloading, although that could have been because of me using
addon_enable
:')This issue was referenced by blender/blender@ee4ec69b28
Changed status from 'Archived' to: 'Resolved'
Added subscriber: @antoniov
Changed status from 'Resolved' to: 'Open'
Sorry, closed by error.
Changed status from 'Open' to: 'Archived'
Added subscriber: @JosephDavies
Added subscriber: @1029910278
Recently , I notice that use reload() will destory the socket connection(when it became complex) on win. (win 10054 error)