First introduce how to find out, the line of the project log is through the logging module to the Syslog, ran for a period of time to find the syslog UDP connection over 8W, yes 8 W. The main logging module is wrong.
One of the requirements we had before is to output the current connection information for each connection log, so each connection creates a log instance, assigns a Formatter, and creates a log instance in order to differentiate the other connections so I simply rudely use the ID of the current object as the log name:
Import Loggingclass Connection (object): def __init__ (self): self._logger_name = "connection.{}". Format (self) Self.logger = Logging.getlogger (self._logger_name)
Of course the test environment is open debug, debug will not go to the syslog, so there will not be too many UDP connections, you will not know that there is memory leaks, we have to see why this leads to memory leaks, first look at the GetLogger code:
def getLogger (Name=none): "" " Return a logger with the specified name, creating it if necessary. If No name is specified, return the root logger. "" " If Name: return Logger.manager.getLogger (name) else: return root
The main call to Logger.manager.getLogger, this function has the following snippet of code
If name in self.loggerdict: RV = self.loggerdict[name] if Isinstance (RV, PlaceHolder): ph = RV RV = (self . Loggerclass or _loggerclass) (name) Rv.manager = self self.loggerdict[name] = RV self._fixupchildren (ph, RV) self._fixupparents (RV) else: RV = (Self.loggerclass or _loggerclass) (name) Rv.manager = self Self.loggerdict[name] = RV self._fixupparents (RV)
Logging module in order to ensure that the same name refers to the same log instance, so that all the log instances exist in a loggerdict dictionary, so unless the program exits, the created log instance reference is not freed, so the log instance of the handlers will not be released. Previously I used the ID of the object as part of the log name, so the UDP connection created by Sysloghandler has been occupied resulting in excessive UDP connections.
To solve this problem, I added the following code when the connection was closed:
Logging. Logger.manager.loggerDict.pop (self._logger_name) Self.logger.manager = Noneself.logger.handlers = []
Supposedly only add the first line above the code should be released, but no, so there is a third line of code, Sysloghandler finally released, the problem is not yet know why, but also need to check.
2015-03-30 Update if the journal name is in. Delimited, the logging module takes the last part as the log name and looks up for the parent Logger, and if not found, creates the PlaceHolder object as the parent and references Logger.
For example, the Logger name created is called A.B.C, then the actual name is C, and B is the parent of C, and A is the parent of B, if Logger without that name creates a PlaceHolder object instead, PlaceHolder creates a replacement for the current A reference to the Logger. So the name of the log object that needs to be recycled should not be included.