草庐IT

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

coder 2024-06-18 原文

使用 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() 中设置什么,都将成为整个脚本的最终结果。它不是此设置的理想位置,因此应移至其他位置(最好在顶部,最好在类之外)。
  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/

有关Python Windows 服务 - 日志记录不起作用的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  4. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  5. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  6. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  7. ruby-on-rails - Rails 5 Active Record 记录无效错误 - 2

    我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa

  8. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  9. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

  10. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

随机推荐