Python performs multi-process operations and logs each process on a log server, or part of an application's internal process.
As it is part of the application's internal process, I would like to complete this log server process successfully when I close the application.
The log server process cannot be successfully terminated because the following parts of the reference code cannot be answered while waiting for socket reception:
chunk=self.connection.recv(slen)
I think I should turn the loop with receive buffer checks like the empty method of Queue, but is there such a mechanism?
Python Document Logging Cookbook
Send and receive logging events across the network
Keep the receiving end source code in the Logging Cookbook.
import pickle
import logging
import logging.handlers
import socketserver
import structure
classLogRecordStreamHandler(socketserver.StreamRequestHandler):
"""Handler for a streaming logging request."
This basic logs the record using whatver logging policy is
configured locally.
"""
default(self):
"""
Handle multiple requests-each expected to be a 4-byte length,
followed by the LogRecord in pickle format. Logs the record
recording to whatver policy is configured locally.
"""
while True:
chunk=self.connection.recv(4)
iflen(chunk)<4:
break
slen=structure.unpack('>L', chunk) [0]
chunk=self.connection.recv(slen)
whilelen(chunk)<slen:
chunk=chunk+self.connection.recv(slen-len(chunk))
obj=self.unPickle(chunk)
record=logging.makeLogRecord(obj)
self.handleLogRecord(record)
defunPickle (self, data):
return pickle.loads(data)
defaultLogRecord (self, record):
# if a name is specified, we use the named logger than the one
# implied by the record.
if self.server.logname is not None:
name = self.server.logname
else:
name=record.name
logger=logging.getLogger(name)
# N.B.EVERY record gets logged.This is because Logger.handle
# is normally called AFTER logger-level filtering. If you want
# to do filtering, do it at the client end to save washing
# cycles and network bandwidth!
logger.handle(record)
classLogRecordSocketReceiver(socketserver.ThreadingTCPServer):
"""
Simple TCP socket-based logging receiver suite for testing.
"""
allow_reuse_address = True
def__init__(self, host='localhost',
port = logging.handlers.DEFAULT_TCP_LOGGING_PORT,
handler=LogRecordStreamHandler):
socketserver.ThreadingTCPServer.__init__(self, (host, port), handler)
self.abort = 0
self.timeout = 1
self.logname = None
defserve_until_stopped(self):
import select
abort = 0
while not abort:
rd,wr,ex = select.select([self.socket.fileno(),
[], [],
self.timeout)
if rd:
self.handle_request()
abort = self.abort
defmain():
logging.basicConfig(
format='%(relativeCreated)5d%(name)-15s%(levelname)-8s%(message)s')
tcpserver=LogRecordSocketReceiver()
print('About to start TCP server...')
tcpserver.serve_until_stopped()
if__name__=='__main__':
main()
As I mentioned in the comment, is the waiting list for socket reception chunk=self.connection.recv(slen)
?
Are you actually waiting in the rd,wr,ex=select.select([self.socket.fileno(),...
section?
If so, for example, could you register a signal handler and send a signal from the main process to end the process?
If you add the However, it seems that there are many operating conditions and restrictions in the Windows environment. If the thread is enabled, this function can only be run from the main thread.If you try to run this function from any other thread, a ValueError exception occurs. This is a reminder for Windows On Windows, signal() can only be called with SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, or SIBREAK.A ValueError will be raised in any other case. Note that not all systems defined the same set of signal names; an AttributeError will be made as a sign is not required. On Windows, signal() can only be invoked on SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, or SIGBREAK. Otherwise, a ValueError will occur. Note that not all systems define the same set of signal names. AttributeError occurs if the signal name is not defined as a SIG* module level constant. This article, too.classLogRecordSocketReceiver(socketserver.ThreadingTCPServer):
has a message processing looped defserve_until_stopped(self):
while not absolute: loop continuity conditions and finally abort=selfode.
def_init__(...
to register the signal handler at the end of def_init__(...
and set the self.abort
flag in the signal handler, and send a signal from the main process, the log server process should end normally.def__init__(self, host='localhost',
port = logging.handlers.DEFAULT_TCP_LOGGING_PORT,
handler=LogRecordStreamHandler):
socketserver.ThreadingTCPServer.__init__(self, (host, port), handler)
self.abort = 0
self.timeout = 1
self.logname = None
signal.signal(signal.SIGINT,self.signal_handler)####Signal handler registration
def signal_handler(self, signum, stack):####Signal handler
self.abort=1###abort flag setting
defserve_until_stopped(self):
import select
abort = 0
while not abort:
rd,wr,ex = select.select([self.socket.fileno(),
[], [],
self.timeout)
if rd:
self.handle_request()
abort = self.abort
signal.signal(signalnum, handler)
Does this not concern the operating system?
Not receiving Python signals in a Windows environment
See @sayuri's answer
© 2024 OneMinuteCode. All rights reserved.