对以下计划的略微澄清

时间:2014-12-30 10:54:00

标签: python

我从堆栈流程线程之一中取了这个例子。 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类没有这些方法。只是想知道这些电话是如何进行的?有人可以解释一下,这样我可以更好地理解吗?

2 个答案:

答案 0 :(得分:1)

logger.writelogger.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!')