Call Python function from other Python script

Hi!

TL;DR:
I have troubles finding a solution for a Python related problem.
I want to call a function in a Python script from another Python script while the simulation is not running.

Let’s say that I have a component ‘talker’:

image
This component has a button and a Python script that is linked to the button. When I click this button, I can launch the function talker() which in turn calls a function that makes the talker say ‘Hello’. This works perfectly fine as a way to manually launch a piece of Python code.

# talker::say_hello
from vcScript import *

app = getApplication()
comp = getComponent() 


def talker(arg):
  say_hello()
  
  
def say_hello():
  print('Hello!')
 

button = comp.getProperty('talker')
button.OnChanged = talker

Now, let’s say that I have another component ‘guest’. This guest expects that the talker kindly says hello, and therefore I have a very similar button-script setup to manually launch this request:

# guest::say_hello_to_me
from vcScript import *

app = getApplication()
comp = getComponent() 

def say_hello_to_me(arg):
  # Here I want to call say_hello() from talker.py
  

button = comp.getProperty('say_hello_to_me')
button.OnChanged = say_hello_to_me

However, I am not able to call say_hello() that resides in talker::say_hello, now from guest::say_hello_to_me. Calling this function in the first script itself was - not surprisingly - possible, but I actually want to call it from outside.

Some options I tried, but FAILED:

  • finding the VcScript object and importing it:
from app.findComponent('talker').findBehaviour('say_hello') import say_hello
say_hello()
  • trying to call the function with a prefix:
talker = app.findComponent('talker').findBehaviour('say_hello')
talker.say_hello()

I found a workaround by adding a Signal property to the ‘talker’ component. I put my functionality in the OnSignal() event handler, and I am able to successfully launch the functionality from the other Python script:

app.findComponent('talker').findBehaviour('my_signal').signal('')

However, this is only possible when the simulation is running. Now, my implementation becomes very slow compared to when I launch my functionality manually by using the buttons.
I am aware that Python can be used in different ways, maybe I should not implement my functionality in component behaviours? Although for launching everything manually my approach worked very well.

So my question boils down to: How can I call a Python function (def) from another Python script while the simulation is not running?

Scripts run isolated from each other in VC and the intended way to communicate between components is by using interface connections, including signals in those interfaces and actions (action container) for more complex messaging.

Generally implementing script logic which does something outside the component when simulation is not running is not the expected way of doing things and is kinda marker of bad simulation design. Some eCat components do react to other components when their interfaces get connected, though.

If you want to implement tools to e.g. automate layout modeling in some ways, it would be better to use Python commands or .NET plugins instead of components that alter themselves or others based on what you have in the layout.

However, if you want to ignore all that and just get the thing done your way, you can set string property values in other components and register scripts to listen for the property value changes. Those events work when the simulation is reset too. The string values can be serialized data in the format of your choice.

1 Like

Thinking about work around. Can you change the ‘talker’ button property value in your
def say_hello_to_me(arg):

Ok,

I looked a bit into Python commands and it seems the way to go for my application. It’s indeed about a tool for automation of layout modeling, and the fact that the functionality was embedded in the components themselves - and use my functionality to take different appearances - introduced some inconveniences that I probably can eliminate if I implement my Python code in the form of commands.

I was also able to link the commands to buttons, so from workflow point of view nothing really changes, only the code resides in a more logical place. And, I can now easily put my code under version control since it is not hidden anymore in the .vcmx file itself.

I based my solution on the following references:

Thank you very much for pointing me in this direction!

Regards,
Toon D.

1 Like

Hi,
I tried this first, but was not able to change the value of the button to trigger the code.
However, I am reformatting my code in the form of Python commands, as suggested by TSy, see my reply above.