2

2.7.5在Windows 下的python中,当FileHandler处于模式时'w'(写入前截断文件)处理程序不会只写入最后一行。在模式下'a'一切都很好。

我的logging.conf文件:

[loggers]
keys=root

[handlers]
keys=consoleHandler,fileHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=NOTSET
handlers=fileHandler

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[handler_fileHandler]
class=FileHandler
level=DEBUG
formatter=simpleFormatter
args=('generator.log', 'a', 'utf8', 0)

[formatter_simpleFormatter]
format=[ %(asctime)s ] [ %(name)s ] [ %(levelname)-5s ] - %(message)s
datefmt=

我的oracle.py文件:

__author__ = 'wbar'
import cx_Oracle
from contextlib import closing
import logging


class Connector(object):
    __connection__ = None
    __user_name__ = None
    __password__ = None
    __tns_name__ = None
    __logger__ = None

    def get_connection(self, auto_connect=True):
        if auto_connect and not self.__connection__:
            self.__logger__.info(u'Connecting into Oracle: %s@%s', self.__user_name__, self.__tns_name__)
            self.__connection__ = cx_Oracle.connect(
                u'%s/%s@%s' % (self.__user_name__, self.__password__, self.__tns_name__))
        return self.__connection__

    def __init__(self, user_name, password, tns_name):
        self.__user_name__ = user_name
        self.__password__ = password
        self.__tns_name__ = tns_name
        self.__logger__ = logging.getLogger('OracleConnector')
        self.__logger__.addHandler(logging.NullHandler())

    def __del__(self):
        self.close_connection()

    def close_connection(self):
        connection = self.get_connection(auto_connect=False)
        if connection:
            self.__logger__.info(u'Closing connection with Oracle: %s@%s', self.__user_name__, self.__tns_name__)
            connection.close()

    def execute(self, sql):
        with closing(self.get_connection().cursor()) as cursor:
            self.__logger__.debug(u'Executing: %s', sql)
            cursor.execute(sql)
            return cursor.fetchall()

最后是我的主文件generator.py

__author__ = 'wbar'
import logging
import logging.config

logging.FileHandler
logging.config.fileConfig('logging.conf')

from oracle import Connector as OracleConnector
DATABASE = OracleConnector(user_name=u'foo', password=u'bar', tns_name=u'db_local')

for line in DATABASE.execute('select * from dual'):
    print(line[0])

logger = logging.getLogger('root')

logger.debug('DEBUG')
logger.info('INFO')
logger.error('ERROR')

在模式'a'日志文件看起来像:

[ 2013-11-13 17:15:25,608 ] [ OracleConnector ] [ INFO  ] - Connecting into Oracle: pms_test@db_impaq_local
[ 2013-11-13 17:15:25,727 ] [ OracleConnector ] [ DEBUG ] - Executing: select * from dual
[ 2013-11-13 17:15:25,730 ] [ root ] [ DEBUG ] - DEBUG
[ 2013-11-13 17:15:25,730 ] [ root ] [ INFO  ] - INFO
[ 2013-11-13 17:15:25,730 ] [ root ] [ ERROR ] - ERROR
[ 2013-11-13 17:15:25,734 ] [ OracleConnector ] [ INFO  ] - Closing connection with Oracle: pms_test@db_impaq_local

在模式'w'日志文件看起来像:

[ 2013-11-13 17:06:24,239 ] [ OracleConnector ] [ INFO  ] - Closing connection with Oracle: pms_test@db_impaq_local
4

1 回答 1

5

logging模块注册了一个关闭所有处理程序的atexit关闭挂钩。'w'这会在 Python 退出时关闭打开的文件对象。

但是,您的oracle.Connector()类有一个__del__方法,当 Python 退出时也会调用该方法。atexit清理全局变量之前的Python 调用,因此这里的确切操作顺序是:

  1. loggingatexit钩子被调用,文件被关闭。
  2. oracle.Connector().__del__()被调用,它调用self.__logger__.info(). 这将重新打开关闭的文件处理程序以记录,截断文件。

为防止这种情况,请在退出 Python之前显式关闭连接器:

DATABASE.close_connection()
于 2013-11-13T16:28:23.083 回答