5
$\begingroup$

I have two scripts. One that runs the main logic and another that holds a set of functions that I want to call. However when I make a change to the functions script it is not updated. I have saved the function script as a file and I can see that the changes have been applied to it but these changes are not reflected when I click run on my main script.

I have tried click run script on my functions script and if I modify it so it contains an error it will tell me but the main script doesn't seem to notice or care. The only way to get Blender to take notice of any changes in my scripts is to close and reopen it! Why is this happening?

Edit

It appears I've not understood how script works in Blender when you're not running the game engine. So my question effectively becomes:

How can I run a script that calls functions in other scripts by clicking a button in Blender?

I understand this could be considered too broad or too different to my original question so I am considering closing this and starting again.

$\endgroup$
14
$\begingroup$

Once a Python module has been imported, it will never be reloaded by the interpreter (that is, not automatically) when source file changes.

Blender has an operator to reload all of its py scripts, triggered by the F8 shortcut (in default keymap).

Now, that will only reload registered addons (and startup/UI scripts), if your addon contains several sub-modules you need to handle their reload yourself, using that kind of construct in your __init__.py addon’s file:

# When bpy is already in local, we know this is not the initial import...
if "bpy" in locals():
    # ...so we need to reload our submodule(s) using importlib
    import importlib
    if "my_submodule" in locals():
        importlib.reload(my_submodule)


# This is only relevant on first run, on later reloads those modules
# are already in locals() and those statements do not do anything.
import bpy
import my_submodule
|improve this answer|||||
$\endgroup$
  • $\begingroup$ Hi mont29, thank you for your answer. I think I understand what you're trying to explain but I didn't realise how different to the game engine this was going to be. I haven't set up an add on or a module, I just assumed I could call a script whenever I needed to. How come this works out of the box with bge but not with bpy? $\endgroup$ – sydan Apr 15 '15 at 11:17
  • $\begingroup$ I don’t know much about BGE, it probably re-reads (reloads) scripts over and over? Anyway, if you are new to addons in Blender, I suggest you have a look around for tutorials, read some already existing ones, and more than everything official doc, which has some nice introductions. In a few words, you need to define an operator, which code will then do whatever you want. $\endgroup$ – mont29 Apr 15 '15 at 12:21
  • $\begingroup$ Thank you for the guidance! I will proceed to read up and learn how to write addons for Blender. $\endgroup$ – sydan Apr 15 '15 at 12:30
  • $\begingroup$ Is it standard practice to use this conditional when developing a multi-file addon in Blender, or are there other ways around the problem? This seems like it would be a fairly common issue, yet this question has relatively few views and upvotes. $\endgroup$ – splic May 9 '18 at 21:08
1
$\begingroup$

I just had the exactly the same problem as OP and mont29's answer helped me figure out the solution for that particular problem.

So this answer applies to running scripts from Text Editor, not from an addon.

To get a submodule script reload every time the main script is run, put this in the main script in place of the usual import statement for the submodule script:

# this really loads the "my_submodule.py" Text only the first time this script is run
import my_submodule 

# this re-loads the "my_submodule.py" Text every time
# (needs the "normal" import statement above to define the module name)
import importlib
importlib.reload(my_submodule)

Yes, that will make the submodule script get loaded twice the first time main script is run - but that is not important because the purpose of all this is to conveniently test scripts.

(Note that, when run from Text Editor, "my_submodule" will not be in locals() unless it is imported with import so testing for it cannot be used to skip reloading it.)

Finally, to answer sydan's updated question about how to run a script from a button, use this code for the execute of the button's operator:

def execute(self, context):
    text_main= bpy.data.texts['my_mainmodule.py']
    context_c = context.copy()
    context_c['edit_text'] = text_main
    bpy.ops.text.run_script(context_c)
    return {'FINISHED'}
|improve this answer|||||
$\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.