How to import external Python module and refresh Dynamo node when changes are made externally?

Hello,

I just started looking at using python inside dynamo. One thing I would like to do is
to have my python code version controlled by git outside of dynamo. The way I am doing it is
with a short python node with:

import sys
sys.path.append(r’C:\git\mystuff’)
import mystuff
OUT = mystuff.doit(IN[0], IN[1]);

where “mystuff.py” is just:

def doit(x, y):
return x*y;

But I noticed that when I change “mystuff.py”, dynamo does not know that there has been a change
to the python code. So I would have to make some bogus edits inside the dynamo python wrapper.
Is there a way to have dynamo load up the python script whenever there are changes inside the
script? Or better yet, just have dynamo load up the python script(s) every time?

Thanks!
-Robert

Try recreating the Python node, perhaps as a copy paste.

Thanks for the suggestion. It looks like with copy/paste, I’ll have to delete the old one, position the new one into place,
and then hook up the output again.

I think any edits to the python node will trigger a new “import”. But that become tedious after a while.
For now, I add a blank line every time I want to have it import new code. I need something like a “refresh” button.

I’ve not done this workflow before, but does the code update when the inputs are changed. If yes, then create a dummy port (non referenced in python) and plug in a bool node you can toggle. Set graph to automatic.

Thanks for the suggestion. I tried it but it does not pick up any changes in the imported python file.

The reason I want to use this workflow is the drawings can get very complicated like a “rats nest”.
I’d rather code in python and leverage the tools available (IDE’s for example) to manage the complexity,
and version control.

I’ll keep trying other things.

-Robert

I strongly suspect the below PR I did a while back is causing this:

It improve re-execution speed by caching the imported modules. The cached engine updates only if the code stored directly in the node changes. Since there’s no way to notify that the code in the modules has changes, there’s no way to notify that the engine needs to be updated.

One possible work-around that comes to mind is to directly execute the content of the py file every time it gets saved with the exec function. (your editor’s text encoding might matter, that’s why I needed to call the replace method there) :

my_module, a, b = IN
exec(my_module.replace('\r','\n') )

OUT = fn1(a, b)

You’d then be able to directly call the functions and classes defined in that module as if you’d imported it as:

from my_module import *

1 Like

Thanks for the explanation. My comments about the workaround:

  1. Often I don’t want to run the code after I save. The edits are work-in-progress and I may not want
    to run it yet. I guess that’s ok … I’ll just ignore the errors until the very last save. But I’ll end up doing
    something like artificially touching the code just to be sure dynamo is running the latest.

  2. My python code is typically organized hierarchically, so some edits in some lower level may not trigger
    the exec, unless I artificially touch the top module.

I tried doing a “reload(module)” but that did not work. That would be my vote.

Is there a way to turn off the code caching?

Thanks!

This is what I ended up doing:

  • Added “reload()” to the python node
  • Using Daniel’s suggestion, I added a bool toggle as input to the python node.
    It is not used inside the python code.
    (Probably more aptly named as “Reload Toggle” instead of “Run Toggle”)
  • If I want the python node to pick up the latest external python code, I toggle the bool node.

This seems to do what I need so far.

Thanks all for the suggestions. Lots more learning to go.

-Robert

3 Likes

Glad you got a solution, albeit not one that’s as pretty as you would have liked. Did you still need to make alterations in your dynamo python code (e.g. extra line), or was the the reload method and reload toggle enough to get it to work?

The toggle is enough. My workflow:

  • Make edits to python code outside of dynamo.
  • When I want to reload in dynamo, I just toggle the bool node.
    Thanks.

I followed these codes, but I got the following error message.
" NameError : name ‘reload’ is not defined [’ File “”, line 5, in < module >\n’]"

:woozy_face:Where did I go wrong?

I use CPython 3 Interpreter with Dynamo Core 2.10.1.3976 & Dynamo Civil 3D 2.10.1.214

Here is my codes:

  1. import sys
  2. import os
  3. sys.path.append(r’C:\Users\User\Dropbox\repos\C3D_SecViewTakeoff’)
  4. import c3d_SecViewTakeoff
  5. reload(c3d_SecViewTakeoff)
  6. OUT = c3d_SecViewTakeoff.my_setUp

I seem to have solved this problem.

import importlib
importlib.reload(my_module)