TypeError:'Logger'对象不可调用

时间:2015-09-23 11:57:34

标签: python oop logging

我有工具,其中使用了一些带继承的类。

这是我的第一个基于OOP的大工具,我对类初始化有点困惑。

下面的大量代码,使 Q 更清晰。

短继承树:

- RDSmanager(object)
    - Options(RDSmanager)
    - AutoEnv(RDSmanager)
    - UnityXMLgenerator(RDSmanager)

完全记录器类是:

class Logger(object):

    def __init__(self, rdsmanager_localpath):

        """Create Logger"""

        self.rdsmanager_localpath = rdsmanager_localpath

        if not os.path.isdir(os.path.join(self.rdsmanager_localpath, 'logs')):
            os.mkdir(os.path.join(self.rdsmanager_localpath, 'logs'))

    def logger(self, modname):

        self.logger = logging.getLogger(modname)

        formatter = logging.Formatter('%(asctime)s  - %(filename)s[LINE:%(lineno)d] - %(name)s.%(funcName)s() - %(message)s')

        self.logger.setLevel(logging.DEBUG)

        filehandler = logging.FileHandler(os.path.join(self.rdsmanager_localpath, 'logs', 'rdsmanager.log'))
        filehandler.setLevel(logging.DEBUG)
        filehandler.setFormatter(formatter)

        consolehandler = logging.StreamHandler()
        consolehandler.setLevel(logging.INFO)

        self.logger.addHandler(filehandler)
        self.logger.addHandler(consolehandler)

主脚本RDSmanager.py包含:

from lib.local.rds_services import Logger
...

class RDSmanager(object):
    ...

    # path to current RDSmanager directory
    # used toi determine where files (generated XML, logs etc) c to store in
    rdsmanager_localpath = os.path.dirname(os.path.abspath(__file__))

    # global logger object
    logger = Logger(rdsmanager_localpath)

接下来,我在其他类中有两个选项 - -c-D

class Options(RDSmanager):

    """Main "selector" for passed options.
       For each option - appropriate Class.method() will be imported, initialized and called."""

    def getopts(self):
        ...
        parser = argparse.ArgumentParser()
        subparsers = parser.add_subparsers()

        # Unity options
        parser_unity = subparsers.add_parser('unity', help='Unity application options')
        parser_unity.set_defaults(func=self.handler_unity)
        ...
            parser_unity.add_argument('-c',
                                  '--confgen',
                                  action='store_true',dest='unity_confgen',
        ...
            parser_unity.add_argument('-D',
                                  '--deployauto',
                                  action='store_true',
                                  dest='unity_autoenv_deploy',
        ...

    def handler_unity(self, options_list):

        ...   

        if options_list.unity_confgen:
            self.logger.logger.info('Running Unity XML files generator.')
            from lib.unity.xml_config_generator import UnityXMLgenerator
            confgen = UnityXMLgenerator()
            # generate application's config.xml
            confgen.config_xml_generator()
            # generate XML files for each module with TAG == 'CLOUD'
            # see lib.unity.unity_services.UnityServices() docstring for details
            confgen.modules_xmls_generator()
        ...

        if options_list.unity_autoenv_deploy:
            self.logger.logger.info('Running developers AutoEnvironment deploy.')
            from lib.unity.autoenv.developers_auto_env import AutoEnv
            auto = AutoEnv()
            auto.deploy()

接下来,每个类都运行logger初始化,即:

class UnityXMLgenerator(RDSmanager):

    def __init__(self):

        print(id(self.logger.logger))
        print(id(self.logger))

        # self.build_type = build_type

        # self.logger.logger(self.__class__.__name__)

        print('self.logger')
        print(self.logger)

        print('self.logger.logger')
        print(self.logger.logger)

        self.logger.logger(self.__class__.__name__)

        ...

class AutoEnv(RDSmanager):

    def __init__(self):

        # self.build_type = build_type

        self.logger.logger(self.__class__.__name__)

使用-c选项时(即 - class UnityXMLgenerator(RDSmanager)直接从class Options(RDSmanager)初始化) - 一切正常:

> RDSmanager.py unity -c
RDSmanager started at 23, Sep 2015 at 14:38:57
Running Unity XML files generator.
39816128
52831184
self.logger
<lib.local.rds_services.Logger object at 0x032623D0>
self.logger.logger
<bound method Logger.logger of <lib.local.rds_services.Logger object at 0x032623D0>>
...

但是 - 从class UnityXMLgenerator(RDSmanager)的方法调用class AutoEnv(RDSmanager)时会出现问题:

def mkconfig(self):
    ...
    confgen = UnityXMLgenerator()
    ...

并运行:

> RDSmanager.py unity -D
RDSmanager started at 23, Sep 2015 at 14:43:16
Running developers AutoEnvironment deploy.
Story NG-5859-developers-auto-env-build-config status checked - OK
39011216
52678608
self.logger
<lib.local.rds_services.Logger object at 0x0323CFD0>
self.logger.logger
<logging.Logger object at 0x02534390>
Traceback (most recent call last):
  File "D:\Dropbox\RDS\rdsmanager_NG-1\RDSmanager.py", line 258, in <module>
    rds.getopts()
  File "D:\Dropbox\RDS\rdsmanager_NG-1\RDSmanager.py", line 176, in getopts
    res.func(res)
  File "D:\Dropbox\RDS\rdsmanager_NG-1\RDSmanager.py", line 228, in handler_unity
    auto.deploy()
  File "D:\Dropbox\RDS\rdsmanager_NG-1\lib\unity\autoenv\developers_auto_env.py", line 95, in deploy
    self.mkconfig()
  File "D:\Dropbox\RDS\rdsmanager_NG-1\lib\unity\autoenv\developers_auto_env.py", line 70, in mkconfig
    confgen = UnityXMLgenerator()
  File "D:\Dropbox\RDS\rdsmanager_NG-1\lib\unity\xml_config_generator.py", line 32, in __init__
    self.logger.logger(self.__class__.__name__)
TypeError: 'Logger' object is not callable

问题是:

  1. 为什么我从confgen = UnityXMLgenerator()运行class Options(RDSmanager) - 对象self.logger.logger是“<bound method Logger.logger of <lib.local.rds_services.Logger object at 0x032623D0>>” - 但它是“<logging.Logger object at 0x02534390>” - 当它从class RDSmanager(object)初始化时{1}}的子类班AutoEnv(RDSmanager)confgen = UnityXMLgenerator()
  2. 究竟是什么意思“<logging.Logger object at 0x02534390>”和“<bound method Logger.logger of <lib.local.rds_services.Logger object at 0x032623D0>>”?
  3. 我在这里做错了什么,如何找到这个问题的解决方案?

1 个答案:

答案 0 :(得分:7)

您同时拥有名为logger的实例属性logger方法。你不能同时拥有:

def logger(self, modname):
    self.logger = logging.getLogger(modname)

该实例属性logger使用相同的名称屏蔽该方法。使用其他名称。