Please describe how to make add-on development more efficent (e.g. reloading) #67387

Open
opened 4 years ago by NumesSanguis-3 · 17 comments

Problem


No clear documentation on how to setup an efficient development environment and reload an add-on during development, leading to slow and frustrating experiences by newer add-on developers.

Explanation


Imagine being a new add-on developer who just finished the Add-on Tutorial (https://docs.blender.org/manual/en/dev/advanced/scripting/addon_tutorial.html#intended-audience). You wrote a .py file and wonder, do I really need to add every .py file through Preferences ‣ Add-ons ‣ Install…?

  • Please mention that you can set a default script location with: Edit ‣ Preferences ‣ File Paths ‣ Data ‣ Scripts.

Next, we realize you rather write "create blocks" as "Create Blockies", but wait, or add-on is already loaded. How do I reload the add-on? Do I really have to close Blender every time? With your Google skills (https:*blender.stackexchange.com/questions/2691/is-there-a-way-to-restart-a-modified-addon) you find that F8 should reload all add-ons... except it doesn't, because that's for 2.79. Luckily you read through the comments and realize you have to go through the painful process of searching for F3 -> reload scripts -> enter every time we need to reload a change. In the other answer you find bpy.ops.wm.addon_enable(module='your_module_name') for in the Blender terminal, which might be slightly faster (just arrow-up -> enter). You continue for a while and started to make a multi-file add-on. Suddenly your code shortcut doesn't reload every change you make? After some experimenting you find out that only changes in __init__.py are noticed, so you go to (https:*blender.chat/channel/python) and ask what is wrong (https:*blender.chat/channel/python?msg=fGEyJtjNZqfpApxQ5). Which doesn't solve your issue, so you dive in the code of ``bpy.ops.wm.addon_enable()and make an issue about it (https:*developer.blender.org/T66924). There, someone points out that actuallybpy.ops.script.reload()is the right code command, notbpy.ops.wm.addon_enable(module='your_module_name')`

  • Please mention that you can reload ALL add-ons with F3 -> reload scripts -> enter or the correct code line bpy.ops.script.reload().

You hear you can set a keyboard shortcut for reload, so you find an image about it (https:*devtalk.blender.org/t/reload-button-in-2-8/1708). The image there doesn't tell you how to set the keyboard shortcut and Preferences -> Keymap -> Search -> "reload script" doesn't show up anything. So you Google now: "Blender 2.8 how to add a new shortcut", which shows only "Blender 2.8 changed these shortcuts!", so you add "your own", only to find this page saying it has not been implemented yet (https:*blender.stackexchange.com/questions/124475/blender-2-8-how-to-add-a-new-shortcut). Then in a 2.79 YouTube video you find you first have to collapse a line (e.g. Screen -> Global where a button Add New shows up.

  • Please include in the docs how to set a keyboard shortcut for add-on reloading: Preferences -> Keymap -> Screen -> Screen (Global) -> Add New -> collapse -> see image.
    Blender2.80_script_reload_shortcut.png

  • Please also include (a link to) how to setup an IDE to develop your add-ons with.

Add-on reloading

Please also include that the beginning of your file needs a structure like this if you want to reload add-ons:

# Check if this add-on is being reloaded
if "bpy" in locals():
    # reloading .py files
    import importlib
    - from . blendzmq_props import ZMQSocketProperties
    - importlib.reload(ZMQSocketProperties)
    - from . blendzmq_panel import BLENDZMQ_PT_zmqConnector
    - importlib.reload(BLENDZMQ_PT_zmqConnector)

    from . import addon_props  # addon_props.py (properties are created here)
    importlib.reload(addon_props)  # does this file need a def register() / def unregister() for the classes inside?
    from . import addon_panel  # addon_panel.py (panel interface classes are created here)
    importlib.reload(addon_panel)
# or if this is the first load of this add-on
else:
    print("importing .py files")
    import bpy
    from . import addon_props
    from . import addon_panel

Request


By reading this, you might have noticed that getting into efficient Blender add-on development is quite frustrating with the current documentation. Please make an extra page about how to setup you add-on development environment, using the bullet points above, here: https://docs.blender.org/manual/en/dev/advanced/scripting/addon_tutorial.html#intended-audience

Problem **** No clear documentation on how to setup an efficient development environment and reload an add-on during development, leading to slow and frustrating experiences by newer add-on developers. Explanation **** Imagine being a new add-on developer who just finished the Add-on Tutorial (https://docs.blender.org/manual/en/dev/advanced/scripting/addon_tutorial.html#intended-audience). You wrote a .py file and wonder, do I really need to add every .py file through `Preferences ‣ Add-ons ‣ Install…`? - Please mention that you can set a default script location with: `Edit ‣ Preferences ‣ File Paths ‣ Data ‣ Scripts`. Next, we realize you rather write "create blocks" as "Create Blockies", but wait, or add-on is already loaded. How do I reload the add-on? Do I really have to close Blender every time? With your Google skills (https:*blender.stackexchange.com/questions/2691/is-there-a-way-to-restart-a-modified-addon) you find that F8 should reload all add-ons... except it doesn't, because that's for 2.79. Luckily you read through the comments and realize you have to go through the painful process of searching for `F3 -> reload scripts -> enter` every time we need to reload a change. In the other answer you find `bpy.ops.wm.addon_enable(module='your_module_name')` for in the Blender terminal, which might be slightly faster (just arrow-up -> enter). You continue for a while and started to make a multi-file add-on. Suddenly your code shortcut doesn't reload every change you make? After some experimenting you find out that only changes in `__init__.py` are noticed, so you go to (https:*blender.chat/channel/python) and ask what is wrong (https:*blender.chat/channel/python?msg=fGEyJtjNZqfpApxQ5). Which doesn't solve your issue, so you dive in the code of ``bpy.ops.wm.addon_enable()` and make an issue about it (https:*developer.blender.org/T66924). There, someone points out that actually `bpy.ops.script.reload()` is the right code command, not `bpy.ops.wm.addon_enable(module='your_module_name')` - Please mention that you can reload ALL add-ons with `F3 -> reload scripts -> enter` or the correct code line `bpy.ops.script.reload()`. You hear you can set a keyboard shortcut for reload, so you find an image about it (https:*devtalk.blender.org/t/reload-button-in-2-8/1708). The image there doesn't tell you how to set the keyboard shortcut and `Preferences -> Keymap -> Search -> "reload script"` doesn't show up anything. So you Google now: "Blender 2.8 how to add a new shortcut", which shows only "Blender 2.8 changed these shortcuts!", so you add "your own", only to find this page saying it has not been implemented yet (https:*blender.stackexchange.com/questions/124475/blender-2-8-how-to-add-a-new-shortcut). Then in a 2.79 YouTube video you find you first have to collapse a line (e.g. `Screen -> Global` where a button `Add New` shows up. - Please include in the docs how to set a keyboard shortcut for add-on reloading: `Preferences -> Keymap -> Screen -> Screen (Global) -> Add New -> collapse -> see image`. ![Blender2.80_script_reload_shortcut.png](https://archive.blender.org/developer/F7621818/Blender2.80_script_reload_shortcut.png) - Please also include (a link to) how to setup an IDE to develop your add-ons with. Add-on reloading --------------------- Please also include that the beginning of your file needs a structure like this if you want to reload add-ons: ``` # Check if this add-on is being reloaded if "bpy" in locals(): # reloading .py files import importlib - from . blendzmq_props import ZMQSocketProperties - importlib.reload(ZMQSocketProperties) - from . blendzmq_panel import BLENDZMQ_PT_zmqConnector - importlib.reload(BLENDZMQ_PT_zmqConnector) from . import addon_props # addon_props.py (properties are created here) importlib.reload(addon_props) # does this file need a def register() / def unregister() for the classes inside? from . import addon_panel # addon_panel.py (panel interface classes are created here) importlib.reload(addon_panel) # or if this is the first load of this add-on else: print("importing .py files") import bpy from . import addon_props from . import addon_panel ``` Request **** By reading this, you might have noticed that getting into efficient Blender add-on development is quite frustrating with the current documentation. Please make an extra page about how to setup you add-on development environment, using the bullet points above, here: https://docs.blender.org/manual/en/dev/advanced/scripting/addon_tutorial.html#intended-audience
Poster

Added subscriber: @NumesSanguis-3

Added subscriber: @NumesSanguis-3
NumesSanguis-3 changed title from Please describe how to make add-on development more efficent to Please describe how to make add-on development more efficent (e.g. reloading) 4 years ago
Collaborator

Added subscriber: @JacquesLucke

Added subscriber: @JacquesLucke
Collaborator

Just a quick note, addon reloading can also be done differently. This Visual Studio code extension does the reloading automatically: https://marketplace.visualstudio.com/items?itemName=JacquesLucke.blender-development

Personally, I'm not really a big fan of the reloading code you mention, but yeah, it is used in many addons...

Just a quick note, addon reloading can also be done differently. This Visual Studio code extension does the reloading automatically: https://marketplace.visualstudio.com/items?itemName=JacquesLucke.blender-development Personally, I'm not really a big fan of the reloading code you mention, but yeah, it is used in many addons...

Added subscriber: @JosephDavies

Added subscriber: @JosephDavies
Collaborator

Added subscriber: @dr.sybren

Added subscriber: @dr.sybren
Collaborator

The reload code is incorrect. The return value of importlib.reload() should be assigned to the local name of the reloaded module, or addon_props and addon_panel will still refer to the old module.

This style of addon reloading code fixes that, and as an added benefit it is also compatible with MyPy type checking:

import bpy

# Check if this add-on is being reloaded
if "addon_props" not in locals():
    from . import addon_props, addon_panel
else:
    import importlib

    addon_props = importlib.reload(addon_props)
    addon_panel = importlib.reload(addon_panel)

By not checking the name "bpy" but one of the addon's imported modules, it's also possible to just import bpy like any other module, and have the PEP 8 suggested order of "standard library", "third party", "own code" in the imports.

The MyPy compatibility comes from having the import first, and the reload later. This makes it possible to parse the file top-to-bottom. I suspect that some IDEs may also prefer this order.

The reload code is incorrect. The return value of `importlib.reload()` should be assigned to the local name of the reloaded module, or `addon_props` and `addon_panel` will still refer to the old module. This style of addon reloading code fixes that, and as an added benefit it is also compatible with MyPy type checking: ``` import bpy # Check if this add-on is being reloaded if "addon_props" not in locals(): from . import addon_props, addon_panel else: import importlib addon_props = importlib.reload(addon_props) addon_panel = importlib.reload(addon_panel) ``` By not checking the name "bpy" but one of the addon's imported modules, it's also possible to just `import bpy` like any other module, and have the PEP 8 suggested order of "standard library", "third party", "own code" in the imports. The MyPy compatibility comes from having the import first, and the reload later. This makes it possible to parse the file top-to-bottom. I suspect that some IDEs may also prefer this order.
zgorg commented 3 years ago

Added subscriber: @zgorg

Added subscriber: @zgorg
zgorg commented 3 years ago

This comment was removed by @zgorg

*This comment was removed by @zgorg*
zgorg commented 3 years ago
plz watch this https://youtu.be/QrNr4U17v3w

Added subscriber: @bunnybones

Added subscriber: @bunnybones

I have the same gripes. To make matters worse, running bpy.ops.script.reload() causes blender to crash for me. I'll keep looking for that better workflow as well. Hang in there!

I have the same gripes. To make matters worse, running `bpy.ops.script.reload()` causes blender to crash for me. I'll keep looking for that better workflow as well. Hang in there!
jmu commented 2 years ago

Added subscriber: @jmu

Added subscriber: @jmu

Added subscriber: @doppioslash

Added subscriber: @doppioslash

Added subscriber: @vromance

Added subscriber: @vromance

I am exploring reinstalling addons (zipping the directory and re install) automatically within Blender with one hotkey (ctrl shift R), while keeping track of several 'work in progress' directories in the user preferences (just check/uncheck which ones should be reinstalled when you switch projects). I know this is not the best solution, but the goal would be to mimic a real (re)install, similar to any user who receives your add-on zipfile and installs it in a fresh Blender install. The reloading / removing modules should definitely be revised and improved, and there are surely some other things that should be handled... But it works pretty well for me so far. (famous last words).

https://github.com/josvromans/blender_reinstall_addons

I am exploring reinstalling addons (zipping the directory and re install) automatically within Blender with one hotkey (ctrl shift R), while keeping track of several 'work in progress' directories in the user preferences (just check/uncheck which ones should be reinstalled when you switch projects). I know this is not the best solution, but the goal would be to mimic a real (re)install, similar to any user who receives your add-on zipfile and installs it in a fresh Blender install. The reloading / removing modules should definitely be revised and improved, and there are surely some other things that should be handled... But it works pretty well for me so far. (famous last words). https://github.com/josvromans/blender_reinstall_addons
drewp commented 2 years ago

Added subscriber: @drewp

Added subscriber: @drewp
hyyou commented 1 year ago

Added subscriber: @hyyou

Added subscriber: @hyyou
Blendify removed the
legacy project/Documentation
label 2 days ago
Blendify removed the
legacy module/Python API
label 2 days ago
Sign in to join this conversation.
No Label
good first issue
legacy module/Animation & Rigging
legacy module/Core
legacy module/Development Management
legacy module/Eevee & Viewport
legacy module/Grease Pencil
legacy module/Modeling
legacy module/Nodes & Physics
legacy module/Pipeline, Assets & IO
legacy module/Platforms, Builds, Tests & Devices
legacy module/Python API
legacy module/Rendering & Cycles
legacy module/Sculpt, Paint & Texture
legacy module/User Interface
legacy module/VFX & Video
legacy project/2.81
legacy project/2.82
legacy project/2.83
legacy project/2.90
legacy project/2.91
legacy project/2.92
legacy project/2.93
legacy project/3.0
legacy project/3.1
legacy project/3.2
legacy project/3.3
legacy project/3.4
legacy project/3.5
legacy project/Animation & Rigging
legacy project/Asset Browser Project Overview
legacy project/Audio
legacy project/BF Blender: Next
legacy project/Compositing
legacy project/Core
legacy project/Cycles
legacy project/Datablocks and Libraries
legacy project/Development Management
legacy project/Documentation
legacy project/EEVEE & Viewport
legacy project/Game Engine
legacy project/Game Physics
legacy project/Geometry Nodes
legacy project/Good First Issue
legacy project/Grease Pencil
legacy project/Images & Movies
legacy project/Import/Export
legacy project/Infrastructure: Websites
legacy project/Line Art
legacy project/Modeling
legacy project/Modifiers
legacy project/Nodes
legacy project/Nodes & Physics
legacy project/Physics
legacy project/Pipeline, Assets & I/O
legacy project/Platform: Windows
legacy project/Python API
legacy project/Render & Cycles
legacy project/Sculpt, Paint & Texture
legacy project/Straightforward Issue
legacy project/Tracker Curfew
legacy project/Translations
legacy project/User Interface
legacy project/UV Editing
legacy project/VFX & Video
legacy project/Video Sequencer
Priority › High
Priority › Low
Priority › Normal
Status › Archived
Status › Confirmed
Status › Duplicate
Status › Needs Information from Developers
Status › Needs Information from User
Status › Needs Triage
Status › Resolved
straightforward issue
Type › Bug
Type › Design
Type › Known Issue
Type › Patch
Type › Report
Type › To Do
No Milestone
No project
No Assignees
11 Participants
Notifications
Due Date

No due date set.

Dependencies

No dependencies set.

Reference: blender/documentation#67387
Loading…
There is no content yet.