On Wed, 2009-04-22 at 10:54 -0400, William McVey wrote: > I'm using py.execnet with the SshGateway and I'd like to fire off > logging messages that get sent over the ssh connection. I was wondering > if someone has already coded up a logging handler for this.
After a bit of frustration, I have remote logging over an execnet channel working, with no changes to the py.execnet code itself to support this. I had to resort to a nasty trick in order to get the channel to send and receive the logging.LogRecord objects. I think this could be made a lot cleaner if py.execnet were tweaked to allow defining a dictionary of namespaces to use when deserializing objects coming over a channel. If there is any interest in this by the py lib maintainers, I'll go ahead and fork the code using bitbucket, add this capability in (probably as a new method on the channel object) and issue a pull notification. Anyway, attached is a simple demo script that shows the ExecNetHandler logging handler in action. I'd love to hear feedback on this. -- William
import py, time, logging remote_code = """ import logging class FakeLogRecord(object): "Fakes a LogRecord's repr for passing over an execnet channel" def __init__(self, log): self.log = log def __repr__(self): l = self.log # Serialization of objects going over a channel happens by calling # repr() on the object. Deserialization happens with an # eval(mesg, {}). With a minimal namespace, I need to handle the # importing of the module myself as an expression encoded in the repr # of the object. Currently, I ignore specified traceback objects # attached to a LogRecord via exc_info=True. return "__import__('logging').LogRecord(%r, %r, %r, %r, %r, %r, ())" % ( l.name, l.levelno, l.pathname, l.lineno, l.msg, l.args) class ExecNetHandler(logging.Handler): "Send logging messages over an py.execnet connection" def __init__(self, channel): logging.Handler.__init__(self) self.channel = channel def emit(self, record): obj = FakeLogRecord(record) self.channel.send(obj) # A testrun log = logging.getLogger("remote") log.setLevel(logging.DEBUG) log.addHandler(ExecNetHandler(channel)) log.debug("Starting up") channel.send("Look ma, I'm home") log.info("I'm running on the remote side") try: raise RuntimeError("just an exception") except: log.error("Somebody set up us the bomb", exc_info=True) log.debug("Closing down") """ logging.basicConfig(format="%(name)s: %(levelname)s: %(message)s") remote_log = logging.getLogger("remote") handler = logging.StreamHandler() handler.setLevel(logging.INFO) remote_log.addHandler(handler) gw = py.execnet.PopenGateway() channel = gw.remote_exec(remote_code) time.sleep(2) for mesg in channel: if isinstance(mesg, logging.LogRecord): remote_log.handle(mesg) continue print "From the remote side:", `mesg`
_______________________________________________ py-dev mailing list py-dev@codespeak.net http://codespeak.net/mailman/listinfo/py-dev