我有一个工具,其中使用了一些继承的类。
这是我的第一个基于面向对象编程的大型工具,我对类的初始化有点困惑。
下面有很多代码,为了让这个问题更清晰。
简短的继承树:
- 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
问题是:
- 为什么如果我从
class Options(RDSmanager)
中运行confgen = UnityXMLgenerator()
,则对象self.logger.logger
的值为"<bound method Logger.logger of <lib.local.rds_services.Logger object at 0x032623D0>>
",但是如果从class RDSmanager(object)
的子类classAutoEnv(RDSmanager)
使用confgen = UnityXMLgenerator()
进行初始化,则其值为"<logging.Logger object at 0x02534390>
"? - "
<logging.Logger object at 0x02534390>
"和"<bound method Logger.logger of <lib.local.rds_services.Logger object at 0x032623D0>>
"具体意味着什么? - 我在这里做错了什么,如何解决这个问题?