Error-handling on plugins

Hi, not sure if we are missing some details. However, during prototyping in Houdini, we noticed that the plugins don’t adhere basic python error-handling.

For example, the following validation plugin will simply not show up in the UI and not throw any kind of warning/error. This while we would expect an NameError, since the module pyblish.api.InstancePlugin is never imported and should instead be api.InstancePlugin.

from pyblish import api


class ValidateOutputPath(pyblish.api.InstancePlugin):
    """Validate the output path on the node."""

    order = api.ValidatorOrder
    label = 'Validate output path'
    hosts = ['houdini']

    def process(self, instance):
        """Validate output path."""
        pass

We are wondering if there a way to have Pyblish report an error/warning in the console in such situations, instead of just letting it pass silently?

We register all plugins at startup of Houdini in pythonrc.py by looping over all plugins we want to register and calling pyblish.api.register_plugin

Used versions: pyblish_base-1.8.6, pyblish_lite-0.8.5, pyblish_houdini-1.0.1

Thanks in advance.

Best,
Arlon

Thanks for posting @arlon.sw

I personally think we can improve on this, because even though I’ve been using Pyblish for years now, I can issues troubleshooting a plugin because of this reason.

The error message that you are not seeing occurs here; https://github.com/pyblish/pyblish-base/blob/master/pyblish/plugin.py#L1349
Think you need to setup a logging to listen to the logger pyblish.plugin, and make sure its on DEBUG level.

Suggestions are welcome for a better error reporting!

@tokejepsen Thanks for your reply.

Good to know where this behavior comes from. I’ll will give your tip about the logger a try soon.

Best,
Arlon

Python’s logging module is admittedly a little hard to work with, but what you seek is there, just not very visible.

run_me.py

import os
import shutil
import logging
import tempfile

from pyblish import api

plugins = """\
from pyblish import api

class Validate(api.BAD_InstancePlugin):
    pass

"""

def make_plugins():
    tmpdir = tempfile.mkdtemp()
    fname = os.path.join(tmpdir, "my_plugins.py")

    with open(fname, "w") as f:
        f.write(plugins)

    return tmpdir



if __name__ == '__main__':
    tmpdir = make_plugins()
    api.register_plugin_path(tmpdir)

    # No warnings are emitted?
    api.discover()

    # Because we need to catch them
    log = logging.getLogger("pyblish")

    # For more granular control, each submodule provides its own logger
    # which are all aggregated into this top-level one.

    # Next you need a handler and formatter
    # Some DCCs, like Maya, makes one of these for you. Houdini does not.
    hnd = logging.StreamHandler()
    fmt = logging.Formatter('%(message)s')
    hnd.setFormatter(fmt)
    log.addHandler(hnd)

    # Finally, the default level for any logger is WARNING
    log.setLevel(logging.DEBUG)

    api.discover()
    # Skipped: "my_plugins" (module 'pyblish.api' has no attribute 'BAD_InstancePlugin')

    # Cleanup
    shutil.rmtree(tmpdir)
Skipped: "my_plugins" (module 'pyblish.api' has no attribute 'BAD_InstancePlugin')

In short, Pyblish emits all manners of warnings and errors via the logging module, but separates between warnings for users, and warnings for developers. Developers are expected to setup logging on their own, so as to not flood artist workstations with messages they cannot act on (like syntax errors in a plug-in).

Via the logging module, you can setup a “stream handler” for printing to the terminal, but also file handlers or handlers to your custom GUIs and such.

You’ve also got various levels of granularity.

  • pyblish is the top-level handler, all messages flow through there.
  • pyblish.plugin is a submodule handler, it only emits messages related to plug-ins, like syntax errors
  • pyblish.logic and others provide messages coming from their corresponding module, best to see the individual module descriptions for more details.

Hope it helps. @tokejepsen does this solve the problems you’ve been having too?

For future reference, this information and more can be found in the docs.

Yeah, I tend to just add a print statement cause I’m lazy, but good to know a more proper way of doing it.