Are there any exemplary examples of the GoF Observer implemented in Python? I have a bit code which currently has bits of debugging code laced through the key class (currently generating messages to stderr if a magic env is set). Additionally, the class has an interface for incrementally return results as well as storing them (in memory) for post processing. (The class itself is a job manager for concurrently executing commands on remote machines over ssh).
Currently the usage of the class looks something like:
job = SSHJobMan(hostlist, cmd)
job.start()
while not job.done():
for each in job.poll():
incrementally_process(job.results[each])
time.sleep(0.2) # or other more useful work
post_process(job.results)
An alernative usage model is:
job = SSHJobMan(hostlist, cmd)
job.wait() # implicitly performs a start()
process(job.results)
This all works fine for the current utility. However it does lack flexibility. For example I currently support a brief output format or a progress bar as incremental results, I also support
brief, complete and “merged message” outputs for the post_process() function.
However, I’d like to support multiple results/output streams (progress bar to the terminal, debugging and warnings to a log file, outputs from successful jobs to one file/directory, error messages and other results from non-successful jobs to another, etc).
This sounds like a situation that calls for Observer … have instances of my class accept registration from other objects and call them back with specific types of events as they occur.
I’m looking at PyPubSub since I saw several references to that in SO related questions. I’m not sure I’m ready to add the external dependency to my utility but I could see value in using their interface as a model for mine if that’s going to make it easier for others to use. (The project is intended as both a standalone command line utility and a class for writing other scripts/utilities).
In short I know how to do what I want … but there are numerous ways to accomplish it. I want suggestions on what’s most likely to work for other users of the code in the long run.
The code itself is at: classh.
Well… actually, this looks like a good design to me if an asynchronous API is what you want. It usually is. Maybe all you need is to switch from stderr to Python’s
loggingmodule, which has a sort of publish/subscribe model of its own, what withLogger.addHandler()and so on.If you do want to support observers, my advice is to keep it simple. You really only need a few lines of code.
Your Job class can subclass
Observable. When something of interest happens, callself.fire(type="progress", percent=50)or the like.