Calling functions from a compiled wbex using journaling

Options
Nick Ramseyer
Nick Ramseyer Member Posts: 25
Name Dropper First Comment

I recently compiled my ACT wbex and noticed that some functionality in my scripts no longer works. Specifically, I am sending a command to Mechanical from the workbench project page using the wbjn.ExecuteCommand function to call in a function once Mechanical has been opened using model.SendCommand(Language="Python", Command={}).

The issue appears to be that when the wbex compiles it no longer is able to understand an import command of a function in mechanical. This is a good thing as the end user can't see or use the commands from the wbex, but is causing problems as it breaks the code that I am calling to automate workflows between spaceclaim/mechanical.

As an example I have a function that exists within the projects folder structure like this:

The goal is to call the "example function.py" after opening mechanical during journaling.
Currently I did this using an import and then called the function after:
`model.Edit()

model.SendCommand(Language="Python", Command="from folder_of_functions.example_function import example_function

model.SendCommand(Language="Python", Command="example_function()`

The issue being that the function can no longer be imported after the project has been turned into a wbex. Is there a recommended way to call a function using the project page journaling? There is an alternate command that could be used:
“model.SendCommand(Language=‘Python’,Command=‘my_callback()’,ExtensionName=‘My_app’)”

In this case it is unclear if the function needs to be imported in the main.py file? or how it can be loaded/called.

Tagged:

Best Answer

  • Mike.Thompson
    Mike.Thompson Member, Employee Posts: 316
    First Answer First Anniversary First Comment 5 Likes
    Answer ✓
    Options

    @Nick Ramseyer , @Landon Mitchell Kanner ,
    I typically get confused when dealing with the various levels of project scripting vs. mechanical scripting. To avoid confusion I like to implement a wrapper function that does exactly what I want that is located within the main ACT python module. It can for sure import and work with submodules, but the method I call is from the main ACT module (no import statements)

    To call a function from a particular ACT I use the following syntax:

    ThisExtName = ExtAPI.ExtensionManager.CurrentExtension.Name

    Ext = ExtAPI.ExtensionManager.GetExtensionByName('"""+ThisExtName+"""')
    ExtMod = Ext.GetModule()
    ExtMod.DoSomething()

    You can verify the behavior in mechanical that it is doing what you want via the console. To then migrate this to a project page call, you simply dynamically create the same three lines to call any method from any ACT loaded.

    This seems to work well for all the contexts I have tried it.

Answers

  • Landon Mitchell Kanner
    Landon Mitchell Kanner Member, Employee Posts: 256
    First Answer First Comment 5 Likes First Anniversary
    Options

    @Mike.Thompson Do you have a solution for this issue?

  • Landon Mitchell Kanner
    Landon Mitchell Kanner Member, Employee Posts: 256
    First Answer First Comment 5 Likes First Anniversary
    edited February 7
    Options

    Are files and folders being copied to the installation directory (e.g. %appdata%/Ansys/v241/ACT/extensions)?
    If so, I think (I have not tested it) you just need to do something like:

    import sys
    import os
    extension_dir = ExtAPI.ExtensionManager.GetExtensionByName("example").InstallDir
    module_folder = os.path.join(extension_dir ,'folder_of_fuctions')
    sys.path.append(module_folder)
    

    Alternatively, if you want to list example_function.py as a src file in xml, you can use something like:

    dmScript = """
    extension = ExtAPI.ExtensionManager.GetExtensionByName("<Name of extension>").GetModule()
    extension.NewConvectionFunction()"""
    geometry1 = system1.GetContainer(ComponentName="Geometry")
    geometry1.SendCommand(Command=dmScript,Language="Python")
    

    In this way, you hide the source code for example_function from the end user.

  • Nick Ramseyer
    Nick Ramseyer Member Posts: 25
    Name Dropper First Comment
    Options

    I can take a look at that! the other wrench I'll throw in is that it would be needed to have the code not visible to the end users (so in the xml having compiled="true"). So, I'm not sure I can retrieve the functions this way.

  • Landon Mitchell Kanner
    Landon Mitchell Kanner Member, Employee Posts: 256
    First Answer First Comment 5 Likes First Anniversary
    Options

    The second method should work regardless of whether compiled="true". For the first method, you might be able to hide the source code by using a .pyc file instead of .py (again, haven't tried it).