我从堆栈流程线程之一中取了这个例子。 How do I get timestamps in logfile of pexpect
在此代码上,调用Logger类中的用户定义函数_write和_doNothing。
import logging
import pexpect
import re
# this is the method called by the pexpect object to log
def _write(*args, **kwargs):
content = args[0]
# Ignore other params, pexpect only use one arg
if content in [' ', '', '\n', '\r', '\r\n']:
return # don't log empty lines
for eol in ['\r\n', '\r', '\n']:
# remove ending EOL, the logger will add it anyway
content = re.sub('\%s$' % eol, '', content)
return logger.info(content) # call the logger info method with the reworked content
# our flush method
def _doNothing():
pass
logger = logging.getLogger('foo')
hdlr = logging.FileHandler('/bar.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)
# give the logger the methods required by pexpect
logger.write = _write
logger.flush = _doNothing
p = pexpect.spawn('echo "hello world !"', logfile=logger)
logger类没有这些方法。只是想知道这些电话是如何进行的?有人可以解释一下,这样我可以更好地理解吗?
答案 0 :(得分:1)
logger.write
和logger.flush
分别是同一模块中用户定义函数_write()
和_doNothing()
的简单别名。想象一下简化的场景,
# User defined function
>>> def _write():
... print 'Inside _write()'
# Sample Logger class
>>> class Logger:
... pass
# Object of type Logger
>>> logger = Logger()
# Simply adding a new attribute 'write' to the object 'logger'
# and point to the user defined function name.
# This will create an alias.
>>> logger.write = _write
>>> logger.write()
Inside _write()
# Proof that both 'logger.write' and '_write' are indeed
# same
>>> id(logger.write) == id(_write)
简而言之,_write()
类中没有Logger
,但是,您仍然可以为对象创建属性并为其指定别名以引用用户定义的函数。
这正是上面代码中发生的事情。
答案 1 :(得分:1)
继续Pankaj的回答(这是正确的),您甚至可以使用self
绑定types.MethodType
免费功能:
import types
class Foo:
def _print(self, msg):
print("_print(self=%s, msg='%s')" % (self, msg))
def hello(self, name):
self._print("Hello, %s!" % name)
def my_print(self, msg):
print("my_print(self=%s, msg='%s')" % (self, msg))
# Normal call
foo = Foo()
foo.hello("foobar")
# Swap _print with my_print, binding it to a method so you can use `self`
foo._print = types.MethodType(my_print, foo, Foo)
foo.hello("foobar")
打印:
_print(self=<__main__.Foo instance at 0x7f958e772098>, msg='Hello, foobar!')
my_print(self=<__main__.Foo instance at 0x7f958e772098>, msg='Hello, foobar!')