类型错误:'Logger' 对象不可调用。

3

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

这是我的第一个基于面向对象编程的大型工具,我对类的初始化有点困惑。

下面有很多代码,为了让这个问题更清晰。

简短的继承树:

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

Logger类的作用是:

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 Options(RDSmanager)初始化的class UnityXMLgenerator(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 AutoEnv(RDSmanager)的方法调用class UnityXMLgenerator(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. 为什么如果我从class Options(RDSmanager)中运行confgen = UnityXMLgenerator(),则对象self.logger.logger的值为"<bound method Logger.logger of <lib.local.rds_services.Logger object at 0x032623D0>>",但是如果从class RDSmanager(object)的子类class AutoEnv(RDSmanager)使用confgen = UnityXMLgenerator()进行初始化,则其值为"<logging.Logger object at 0x02534390>"?
  2. "<logging.Logger object at 0x02534390>"和"<bound method Logger.logger of <lib.local.rds_services.Logger object at 0x032623D0>>"具体意味着什么?
  3. 我在这里做错了什么,如何解决这个问题?
1个回答

8

您既有实例属性logger,又有一个名为logger方法。这两者不能同时存在:

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

那个实例属性logger掩盖了同名的方法。请使用不同的名称。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接