Share

Python Hooks Tips

This topic offers a variety of tips when working with Python Hooks. The hooks themselves are documented in the .py files in /opt/Autodesk/<PRODUCT>_<VERSION>/python/. You can find example of hooks in /opt/Autodesk/<PRODUCT>_<VERSION>/python_examples/.

Passing the Project Name Between Hooks

Need to pass the project name between hooks? Use the app_initialized hook. This hook is called whenever the project changes. You can assign the project name passed by the hook to a global variable which can then be read by the other hooks.

global_project_name = ""

def app_initialized(project_name):
    global_project_name == project_name

Environment Variables

DL_PYTHON_HOOK_PATH

Allows you to set the path to the Python hooks files. It behaves similar to other PATH variables.

export DL_PYTHON_HOOK_PATH=/share_1/dev/python_hooks/test:/share_1/dev/python_hooks/production

In the above example, Flame loads the hooks from test first, and then for any undefined hooks, continue to scan production.

DL_DEBUG_PYTHON_HOOKS

Enable to get verbose output from hooks, which should simplify the debugging process. Outputs to the shell about:

  • Which hooks are loaded from which files
  • The data sent to each hook that is triggered

export DL_DEBUG_PYTHON_HOOKS=1

Reloading Hooks From Within the Application

A new hotkey has been added to re-scan hook files while the application is running. This is useful to iteratively test changes during implementation.

By default, this is mapped to Ctrl+Shift+P+H, but can be found in the hotkey editor under the name Scan for python hooks.

Threading Hooks

The python hooks described above block the application until they finish their task. To get around this, you can run a hook in its own thread. The example below provides you with the code required to run render_ended() in a thread separate thread. Comments have been added inline.

from threading import Thread
import atexit

#threads is a list used to keep track of all the threads created
threads = []

def wait_for_threads_at_exit():
    global threads
    if len(threads) > 0:
        for thread in threads:
            print("Waiting for %s" % thread.name)
            # join() waits for the thread to finish before relinquishing
            # control, making sure everything is done before exit.
            thread.join()
    threads = []

# Clean up by Python on exit
atexit.register(wait_for_threads_at_exit)

# The actual code to execute in a thread.
def async_callback(param1, param2):
    print("async_callback(%s, %s)\n" % (str(param1), str(param2)))

# render_ended is the actual hook called by the application,
# with its standard moduleName, sequenceName, and elapsedTimeInSeconds
# parameters.
def render_ended(moduleName, sequenceName, elapsedTimeInSeconds):
    #Creates the separate thread
    thread = Thread(
        target=async_callback,
        name="async callback",
        args=(moduleName, sequenceName, ))
    thread.start()

    # Add to threads[] the just created thread, to keep track and
    # clean up on exit.
    threads.append(thread)

Hooks and Locked Shared Libraries

The user always has access to export hooks in the context menu for Shared Libraries, lock or no lock. But if the shared library is locked when the export hook is called, and if the preset selected by the user re-imports the exported material, and the source clip is in the library, the re-import silently fails.

libwiretapPythonClientAPI.so

libwiretapPythonClientAPI.so is located in /opt/Autodesk/python/<VERSION>/lib/python<PYTHON_VERSION>/site-packages/adsk/. This ensures it is in the right folder for Wiretap calls to be made by the Python hooks.

Note that there is also a symlink in /opt/Autodesk/<PRODUCT>_<VERSION>/python/ to libwiretapPythonClientAPI.so. That way, everything that was working previously should still work.

However you should update your Python hooks to use the site-package libwiretapPythonClientAPI. You can do this by replacing import libwiretapPythonClientAPI with from adsk import libwiretapPythonClientAPI.

exportHook.py

exportHook.py contains all the hooks related to exporting clips.

These hooks are used when the user exports from the application.

Export hooks are called in the following order:

  1. pre_custom_export Optional. Called if required by get_custom_export_profiles. Called when the context menu item defined by getCustomExportProfiles is selected by the user.
  2. pre_export Always called. In a regular export, pre_export is called as the Export window is displayed to the user. In a custom export, called after pre_custom_export.
  3. pre_export_sequence Always called. Called before writing the sequence.
  4. pre_export_asset Always called. When it is called depends on the export option. With Foreground Export, all pre_export_asset are called for each assets immediately in one go. With Background Export, each pre_export_asset is called as each asset job is submitted to Backburner.
  5. post_export_asset Always called. Called after an asset is written. Can be done in backburner as determined by use BackburnerPostExportAsset.
  6. post_export_sequence Always called. Called after post_export_asset.
  7. post_export Always called. Called after post_export_sequence.
  8. post_custom_export Optional: called if required by get_custom_export_profiles. Called after post_export.

Was this information helpful?