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:
pre_custom_export
Optional. Called if required byget_custom_export_profiles
. Called when the context menu item defined by getCustomExportProfiles is selected by the user.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 afterpre_custom_export
.pre_export_sequence
Always called. Called before writing the sequence.pre_export_asset
Always called. When it is called depends on the export option. With Foreground Export, allpre_export_asset
are called for each assets immediately in one go. With Background Export, eachpre_export_asset
is called as each asset job is submitted to Backburner.post_export_asset
Always called. Called after an asset is written. Can be done in backburner as determined by useBackburnerPostExportAsset
.post_export_sequence
Always called. Called afterpost_export_asset
.post_export
Always called. Called afterpost_export_sequence
.post_custom_export
Optional: called if required byget_custom_export_profiles
. Called afterpost_export
.