Python Windows 服务 - 日志记录不起作用

标签 python windows logging service pywin32

使用 Python 3.7、Windows 10 专业版、Pywin32

我有一个测试脚本,它启动服务并在发出不同命令时将一些基本行推送到日志文件中。代码如下:

import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import logging


class AppServerSvc(win32serviceutil.ServiceFramework):
    _svc_name_ = "TestService"
    _svc_display_name_ = "Test Service"
    _svc_description_ = "New Test Service"

    logging.basicConfig(filename='search_server.log', level=logging.INFO)
    logging.info('Class opened')

    def __init__(self, args):
        logging.basicConfig(filename='search_server.log', level=logging.INFO)
        logging.info('Init')
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        socket.setdefaulttimeout(60)


    def SvcStop(self):
        logging.basicConfig(filename='search_server.log', level=logging.INFO)
        logging.info('Stop')
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)


    def SvcDoRun(self):
        logging.basicConfig(filename='search_server.log', level=logging.INFO)
        logging.info('Run')
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_, ''))
        self.main()


    def main(self):
        print("running")
        logging.basicConfig(filename='search_server.log', level=logging.INFO)
        logging.info('Main')


if __name__ == '__main__':
    logging.basicConfig(filename='search_server.log', level=logging.INFO)
    logging.info('Calling Handle Command Line')
    win32serviceutil.HandleCommandLine(AppServerSvc)

我已经完成了基本的故障排除,该服务正在安装、启动、重新启动和删除,没有任何错误。然而,我期望日志文件接收基本输出以显示函数正在被命中,但事实并非如此。

我在管理命令提示符下进行的调用:

C:\PythonScripts\SearchServer>python servicetest.py install
Installing service TestService
Service installed

C:\PythonScripts\SearchServer>python servicetest.py start
Starting service TestService

C:\PythonScripts\SearchServer>python servicetest.py restart
Restarting service TestService

C:\PythonScripts\SearchServer>python servicetest.py remove
Removing service TestService
Service removed

C:\PythonScripts\SearchServer>

日志文件的内容:

INFO:root:Class opened
INFO:root:Calling Handle Command Line
INFO:root:Class opened
INFO:root:Calling Handle Command Line
INFO:root:Class opened
INFO:root:Calling Handle Command Line
INFO:root:Class opened
INFO:root:Calling Handle Command Line

正如您所看到的,每次发出命令时都会调用该服务,但我希望内部函数也会被调用。作为服务和 Python 的新手,我想知道我是否错过了什么?我假设函数名称是预定义的,不需要我设置委托(delegate)来访问它们。我在遇到的任何问题中都没有看到过这种情况。

我当然假设这些函数应该被命中并且它们正在被命中并且能够创建日志?

非常感谢您的帮助。

最佳答案

代码存在一些问题:

  1. logging.basicConfig() 只能调用一次,如果再次调用将不会有任何效果。
  2. 由于代码的自然流程,类定义将在代码中首先被调用,甚至在 block if __name__ == '__main__': 之前被调用。因此,您在类定义中的logging.basicConfig()中设置的任何内容都将成为整个脚本的最终结果。它不是此设置的理想位置,因此应移至其他地方(最好在顶部,最好在类(class)外)。
  3. logging.basicConfig中传入的filename参数应该是绝对文件路径,因为一旦服务开始运行,其当前路径就不会与脚本相同,这样logging就无法找到日志文件。 (该服务的当前工作目录将变为 C:\Python37\lib\site-packages\win32 之类的目录)。
  4. (可选):尽量不要使用根日志记录配置,最好有一个记录器实例供您自己使用。

完成所有这些更改后,脚本将如下所示:

import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import logging.handlers

log_file_path = ""  # mention full path here
mylogger = logging.getLogger("TestLogger")
mylogger.setLevel(logging.INFO)
handler = logging.handlers.RotatingFileHandler(log_file_path)
mylogger.addHandler(handler)

class AppServerSvc(win32serviceutil.ServiceFramework):
    _svc_name_ = "TestService"
    _svc_display_name_ = "Test Service"
    _svc_description_ = "New Test Service"

    mylogger.info('Class opened')

    def __init__(self, args):
        mylogger.info('Init')
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        socket.setdefaulttimeout(60)


    def SvcStop(self):
        mylogger.info('Stop')
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)


    def SvcDoRun(self):
        mylogger.info('Run')
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_, ''))
        self.main()


    def main(self):
        print("running")
        mylogger.info('Main')

if __name__ == '__main__':
    mylogger.info('Calling Handle Command Line')
    win32serviceutil.HandleCommandLine(AppServerSvc)

输出:

Class opened
Init
Run
Main
Class opened
Calling Handle Command Line

关于Python Windows 服务 - 日志记录不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57559440/

相关文章:

c++ - SwitchTothread Windows 的 Linux 选项

windows - 有没有办法在 emacs 启动时指定自定义初始化文件?

mysql - 防止单个查询出现在慢查询日志中

ruby-on-rails - Rails 日志中的缩进

python - 如何使用 django 正确显示用户生成的图像?

python - 如何将贝塞尔曲线拟合到一组数据?

python - Minidom - 检查 XML 中是否存在标签

python - 尝试在 Django 中获取客户端的计算机名

c++ - 在 C++ 中返回运行时可用虚拟内存的大小

logging - Mathematica 中对数图刻度线的指数形式