Output Mechanisms
Toast notifications
Toast notifications are small notifications that appear at the bottom of Workbench and fade away after a few seconds. Scripts that are connected to a running application can use them to provide transient output that the user does not need to dismiss.
The following script demonstrates creating toast notifications with different severity levels.
from mapteksdk.project import Project from mapteksdk.operations import show_toast_notification, Severity if __name__ == "__main__": with Project() as project: show_toast_notification( "Default", "The default severity is information." ) show_toast_notification( "Info", "Everything is fine.", Severity.INFORMATION) show_toast_notification( "Warning", "Something may have gone wrong.", Severity.WARNING) show_toast_notification( "Error", "Something has gone wrong.", Severity.ERROR)
The following animation shows the toast notifications generated by the above script:
-
Toast notifications are appropriate for output where it is not important if the user misses it.
-
Toast notifications are not appropriate for outputs that the user may need to keep.
-
Toast notifications do not halt the script.
-
The default severity for a toast notification is Information.
-
Toast notifications require the script to be connected to a running application.
-
Toast notifications appear in the workbench window and may be delivered late if the workbench is not the active application.
Messages
Messages are a method of output designed to grab the user’s attention. It makes a small window appear in the workbench containing the output, which will not disappear until the user dismisses it. Additionally, warning and error severity messages play a tone and flash the workbench application orange when they appear to attract the user’s attention.
Because messages are very attention grabbing, they should be used sparingly.
The following script demonstrates creating messages with different severity levels:
from mapteksdk.project import Project from mapteksdk.operations import show_message, Severity if __name__ == "__main__": with Project() as project: show_message( "Default", "The default severity is information." ) show_message( "Info", "Everything is fine.", Severity.INFORMATION) show_message( "Warning", "Something may have gone wrong.", Severity.WARNING) show_message( "Error", "Something has gone wrong.", Severity.ERROR)
The messages generated by this script are shown in the below screenshot:
-
Messages are appropriate for output where it is very important that the user notices it.
-
Using too many messages can be very obtrusive. They should be reserved for important information.
-
Messages with a severity of ERROR and WARNING will play a tone when they appear to alert the user that something is wrong.
-
The script will not wait for the user to click Dismiss before continuing.
-
Messages require the script to be connected to a running application.
Template script for message on error
The following script is a template for creating scripts where:
-
If the script finishes without encountering an error, a toast notification notifies the user.
-
If the script encounters an error, a message notifies the user that something is wrong. This includes the type of error raised and the error message similar to if the script was run from the command line, however it omits the stack trace.
import os from mapteksdk.project import Project from mapteksdk.operations import show_message, show_toast_notification, Severity SCRIPT_NAME = os.path.basename(__file__) def do_something_useful(project: Project): """A function which does something useful. Parameters ---------- project The Project to do something useful with. This can be removed if you don't need it when using this template. """ # Remember to rename this function to have a sensible name! # Absolutely do not keep the name as "do_something_useful". if __name__ == "__main__": with Project() as project: try: do_something_useful(project) show_toast_notification(SCRIPT_NAME, "Completed") except Exception as error: message = f"{type(error).__name__}: {str(error)}" show_message(SCRIPT_NAME, message, Severity.ERROR)
What type of output should I use?
A Python script can provide output to the user in many different ways. This section covers different types of output and the appropriate output to use in those situations.
Standard output
For example:
print("Hello world!")
-
The print statement is the easiest way for a script to provide output.
-
If a script is run in a popup shell window, the window is closed when the script finishes and the output is lost.
-
This can make the script difficult to debug, because if it encounters an error then the shell window is immediately closed making it difficult to determine what the error was.
-
-
If the script is run in a window embedded in the workbench (or Visual Studio code) the output window will remain after the script ends.
-
Writing to standard output when running a script in the Extend Python Script workflow component will cause the workflow to pause after the script finishes and require the user to dismiss the message box, so it should be avoided.
-
Standard output is not available for scripts with a .pyw extension. If such scripts are run from the workbench, no popup shell window or embedded window will be opened and thus anything printed will be lost.
-
Saving a script with the .pyw extension instead of .py indicates that the script provides output by other mechanisms.
-
Saving a script with the .pyw extension is a good way to silence the script if opening a shell window or embedded window would be too intrusive.
-
-
Always available to scripts, no imports.
-
The user may not see it, therefore it is not appropriate for important information.
-
It can be obtrusive.
Raising an error
For example:
raise ValueError("Expected the input to be greater than zero.")
-
Raising an error is appropriate when one of the assumptions or requirements of your script turns out to be false. An unhandled error will end the execution of the script, which is typically preferable to continuing if something unexpected has happened.
-
If a function throws an error, the caller can catch it and potentially handle it.
-
A script should never catch an error unless they likely can handle it.
-
-
A good way to stop a script from destroying data because one of its assumptions turned out to be false.
-
Always available to scripts, no imports.
-
If an error is thrown in a function, the caller may be able to catch it. The error may contain additional information that allows the user to handle the error.
-
Errors include a stack trace, which can be useful for determining why the error occurred.
-
By default, unhandled errors are written to standard output and thus they have all the cons of using print.
-
Errors often include a stack trace, which can be intimidating for less technical users.
-
This is relevant to unhandled errors/exceptions. By handling also known as catching the error, you can report it to the user using one of the other methods.
Toast notification
For example:
from mapteksdk.project import Project from mapteksdk.operations import show_toast_notification with Project() as project: show_toast_notification("Toast notification", "Hello world!")
Toast notifications are appropriate for transient information that does not matter if the user misses it.
-
Less obtrusive than other forms of output.
-
Can make the script feel like it is part of the application.
-
Not appropriate for large amounts of output.
-
Not appropriate for output that the user may want to keep or refer back to.
-
Requires an import and a connection to a running application.
-
May be delivered late if the user does not have the application focused.
Message box
For example:
from mapteksdk.project import Project from mapteksdk.operations import show_message with Project() as project: show_message("Message", "Hello world!")
-
Message boxes are appropriate for small amounts of important information.
-
The message box does not disappear until the user dismisses it, so any information reported by a message box cannot be missed by the user.
-
Difficult for the user to miss.
-
Can play a tone when it appears to attract the user’s attention.
-
Can make the script feel like it is part of the application.
-
Not appropriate for large amounts of data.
-
Not appropriate for output the user may want to keep.
-
Very obtrusive.
-
Requires an import and a connection to a running application.
Report window
For example:
from mapteksdk.project import Project from mapteksdk.operations import write_report with Project() as project: write_report("Report", "Hello world!")
-
The report window is appropriate for small to medium amounts of information.
-
Information written to the report window is kept around until the workbench is closed or the user manually clears the report window, which means the user can come back to it when they want to.
-
Not too obtrusive.
-
The data written to the report window stays around until the user closes the workbench or manually clears it, so the user can come back to the data once they are done.
-
Makes the script feel like it is part of the application.
-
Appropriate for medium to large amounts of data.
-
Not appropriate for huge amounts of data.
-
Requires an import and a connection to a running application.
File
For examples, see reading and writing files in the Python documentation.
-
A file is the only way to handle huge amounts of output that user may want to keep.
-
Files are persistent. They will not go away unless the user manually deletes them.
-
You must determine where to put the output file. It must be somewhere the user can find.
-
You must choose the file format (e.g. JSON, CSV, pickle) depending on the intended use of the data.
-
Has greater room for errors.
Advanced: Logging
For examples, see the Python documentation for logging.
Logging is a special type of output designed for the developer of a script rather than the user of the script. Ideally, the user of the script will never see the log messages. Rather, if something goes wrong with the script they send the log files to the developer of the script who can use the content of the log file to help them fix the issue.
By default, log messages are written to standard output however it is often preferable to configure the log to be written to a file in a well-known location. If log messages are written to standard output they have all the same pros and cons as standard output. If log messages are written to a file they have the following pros and cons.
-
Completely unobtrusive. Typically the user will not be aware that logging is happening.
-
Can include information that is too technical, which may intimidate a user of the script.
-
Can include large amounts of information.
-
The log file will stay even if the script crashes. This can make it useful for determining what a script was doing when it crashed.
-
Any information the user may need to see must be written to another output channel.
-
Writing too many log messages can slow down execution of the script.
-
The user needs to know to send the log file to the developer of the script if a problem occurs.
Output type | Obtrusiveness | Maximum data quantity | Appropriate uses |
---|---|---|---|
Standard output (i.e. print) | Moderate | Large | Inconsequential status updates, small amounts of data the user may want to keep, development and initial testing of scripts |
Raising an error (i.e. raise) | High | Small | Notifying the user that something unexpected has happened |
Toast notification | Low | Small | Transient information that the user may miss |
Message | High | Small | Important information that the user should not be allowed to miss |
Report window | Moderate | Medium | Information that the user may want to keep |
File | Low | Very large | Information the user will want to keep or persistent information |
Logging (file) | Low | Very large | Information useful for fixing bugs in the script |