It can be very difficult to get debug information when developing Python scripts in Select – especially developing Automation Code Snippets. This technique provides a welcome solution by writing error/debug information to the system Event Log. Be aware the developer MUST REMOVE the Event Log writer before releasing the code to production.
Setup
Add the following function to the code. To call the function, pass the object for discovery and optionally a label that will be printed in the Event Log. This label can help you find a specific entry if you use multiple Probe calls.
Note: I’m still working on this code.
# Required namespace for Trace class. import System.Diagnostics as SD # Probe writes the object's methods and properties to the Event Log as a Warning event. # o: Object to be inspected. # label: (optional) Label printed in event log to aid finding the message. def Probe(o, label = None): # Build event log message based on object type. s = 'Probe: ' if label is None else 'Probe (' + str(label) + '): ' if isinstance(o, Exception): # Exception! s += 'Python %s exception: %s\n' % (str(type(o).__name__), str(o)) s += '----------------------------------------------------------------\n' if hasattr(o, 'clsException'): s += str(o.clsException) # Add any inner .NET exceptions to end of event log message. innerEx = o.clsException.InnerException exNum = 1 while innerEx is not None: s += '--- INNER EXCEPTION %d ----------------------------------------------\n' % exNum s += str(o.clsException) innerEx = o.clsException.InnerException exNum += 1 # Write exception to event log as "Error". SD.Trace.TraceError(s) return else: # Get object information. s += '%s, %s\n' % (str(o), str(type(o))) c = [str(c) for c in dir(o) if c.startswith('<PID>') == False] if c is not None: s += '["' s += '", "'.join(c) s += '"]\n' # Write to event log as "Warning" to make it easier to find. SD.Trace.TraceWarning(s) # Write to event log as "Warning" to make it easier to find. SD.Trace.TraceWarning(s)
Get Object Information
Pass an object to Probe to get a its type and a list of all methods/properties the object possesses.
# Context is an order. Probe(Context.Underwriters[0].Address)
Generates the following output in the Event Log as a Warning event. It is a bit of a firehose of data, but you are free to modify Probe as you see fit. (Many items omitted to fit in this space.)
Probe: Address, <type 'Address'> ["AddInstance", "Address1", "Address1Address2", "Address2", "Apply", "BeginTrackingChanges", "Build", "City", "CityStateZip", "ClearFormula", ... "ToString", "UseForeignAddress", "Watermark", "Write", "Zip", "__class__", "__delattr__", "__doc__", "__format__", "__getattribute__", "__getitem__", "__hash__", "__init__", "__new__", "__reduce__", "__reduce_ex__", "__repr__", "__setattr__", "__setitem__", "__sizeof__", "__str__", "__subclasshook__"]
Get Exception Information
You can catch exceptions and write the information by enclosing the code in try/except blocks as in the next code block. Any exception occurring inside the try/catch block (or in functions called in the region) will be caught by the “except”. The information is passed to the Probe function, and it is written to the Event Log. The call below adds an optional label: “Ex1”.
try: ... except Exception as ex: Probe(ex, 'Ex1')
Generates the following output in the Event Log as a Warning event. It includes the Python error message and type as well as the .NET error message and type. (Many items omitted to fit in this space.) Any .NET inner exceptions will be listed also.
Probe (Ex1): Python AttributeError exception: 'LookupRow' object has no attribute 'Name' ---------------------------------------------------------------- System.MissingMemberException: 'LookupRow' object has no attribute 'Name' at IronPython.Runtime.Binding.PythonGetMemberBinder.FastErrorGet`1.GetError(CallSite site, TSelfType target, CodeContext context) at Microsoft.Scripting.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame) at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame) ...