本文摘要:本章的主题为用Python实现一个Windows上的服务,我们打开自己电脑上的服务法式,可以看到系统后台启动了许多服务。这些服务在默默的为我们提供了许多功效,可以说我们作为用户,对其看不到摸不着。如果我们也想让自己编写的法式,以服务这种形式在盘算机的后台默默的运行,那该怎么做呢?本章就将围绕这个主题举行学习。

leyu乐鱼全站

本章的主题为用Python实现一个Windows上的服务,我们打开自己电脑上的服务法式,可以看到系统后台启动了许多服务。这些服务在默默的为我们提供了许多功效,可以说我们作为用户,对其看不到摸不着。如果我们也想让自己编写的法式,以服务这种形式在盘算机的后台默默的运行,那该怎么做呢?本章就将围绕这个主题举行学习。

15.1 要解决什么问题我们要解决的问题就是如何用Python语言编写一个可以在Windows上运行的服务,就像Windows系统自身的一些服务法式一样,一直默默的在后台运行,而用户感知不到。那我们这里有几个问题需要解决:· 用Python语言实现一个服务法式;· 该服务法式可以像Windows上的服务一样支持install/start/stop/remove操作;· 将其打包为exe文件,可以在下令行举行执行上述操作;· 将其打包为安装文件,在windows上安装后,服务即可被安装并服务开始运行;· 安装后的服务被卸载时,停止服务,并删除服务;如果能解决上述几个问题,那么我们用Python实现的服务将和Windows自身的服务没什么区别。这样我们就可以将那些需要电脑每次启动后立刻在后台执行的法式都实现为服务,就会很是的利便实用。

好比我们将前面学过的自动毗连Wifi章节的内容实现为服务,因为实际上电脑开机后就需要自动毗连Wifi,开机后每次都手动执行就比力贫苦。所以该功效更适合实现为服务,这里就以此为例来先容如何实现Windows服务法式。15.2 实现思路我们这里的实现思路就是比力简朴,由于是实现Windows上的服务法式,因此比力借助win32serviceutil.ServiceFramework的框架举行实现。这应该也是Python的一大魅力所在吧,我们无须相识win32serviceuntil的详细细节,只需要简朴的使用它来实现我们的服务法式即可。

我们可以将更多的精神放在我们的法式功效上,而无须花费时间和精神在我们不体贴的事情上。win32serviceutil.ServiceFramework模块提供了一些变量名和接口,对于我们来说只需要将相应的变量名赋值为我们自己的内容,并将相关接口举行实现即可。实现了我们的服务类之后,只需要挪用特定servicemanager库举行须要的初始化,就可以实现一个服务法式了。

实现很简朴,也正是简朴,所以才使用Python去解决我们的问题,提高我们的效率。接下来,将先容代码实现中会使用到模块和库。15.3 相关模块的安装及先容本节将会先容我们需要用到的模块或者库。

15.3.1 win32serviceutil模块win32serviceutil模块是一个用于编写windows服务的模块,为我们提供了牢固的框架和接口,便于我们容易的用Python代码编写出自己的windows服务法式。详细使用参考我们的后面的代码实现,因为必须按牢固的框架编写,所以这里不赘述。

15.3.2 win32service模块win32service模块也是编写windows服务法式时需要用到的一个模块,在我们的法式中,只用到了服务停止宏,用于告诉服务控制治理器,当前服务将被停止。详细使用参考我们的后面的代码实现,这里不赘述。15.3.3 win32event模块win32event模块用于建立一个事件,是服务法式需要支持的特性,我们的法式中没有使用到。

不外为了完整性,还是建立了一个事件,但没有做详细的事情。15.3.4 win32timezone模块win32timezone模块用于处置惩罚时间相关的事情,在我们注册服务的时候,会凭据操作系统的时区处置惩罚时间相关的信息。虽然在法式中没有显示的使用该模块,但在安装服务的历程中会使用到该模块,详细的信息可以参考下面的链接。

15.3.5 winerror模块winerror模块,在我们调试,或者服务法式出差时操作系统给给出一些错误码和提示信息,而winerror模块就跟操作系统的错误码有关。15.3.6 servicemanager模块servicemanager服务治理模块,卖力系统中的服务法式治理事务。在我们的法式中,其卖力初始化事情,为安装我们的服务做准备事情,并启动服务控制器。

15.3.7 sys模块sys模块是一个内建模块,不需要单独安装。sys模块提供了对Python解释器使用的一些变量的会见,并可以举行一些修改,例如对情况变量PATH的读取和修改,并提供了某些息争释器举行交互的函数以使我们的法式能够息争释器举行交互。例如,sys.argv会将下令行参数以list的形式通报给Python剧本,sys.argv[0]是剧本的名字,sys.argv[1]是第一个参数,以此类推。

sys.exit()表现退出法式,也可以带参数表现退出码,如果有其他法式挪用该法式,即可以通过返回的数字来确定被挪用法式的退出原因。sys.implementation检察当前正在运行的Python解释器的版本信息。>>> sys.implementationnamespace(cache_tag='cpython-36', hexversion=50726384, name='cpython', version=sys.version_info(major=3, minor=6, micro=5, releaselevel='final', serial=0))>>>sys.stdin,sys.stddout,sys.stderr解释器用于尺度输入,尺度输出和错误。

15.3.8 time模块time模块提供了时间相关的种种函数。time.asctime()函数可以将结构体struct_time所代表的时间转换为这样的字符串'Sun Jun 19 13:31:15 1994'。

我们可以通过time.localtime()函数获得结构体struct_time。time.sleep()函数的入参单元是秒,如果线程需要被挂起,可以通过挪用此函数到达该目的。这里的入参也可以是小数,表现更准确的睡眠时间。我们将会使用该函数举行须要的等候以确保另一件事情竣事。

time.strftime()函数也用于花样化时间。>>> import time>>> time.strftime('%Y%m%d',time.localtime(time.time()))'20190714'>>>>>> time.strftime('%Y-%m-%d')'2019-07-14'>>>15.3.9 subprocess模块subprocess模块,我们可以使用该模块建立一个新的历程。如果需要的话,可以通过入参毗连到法式的输入,输出和错误管道,并通过相应的管道获取法式的输入,输出和错误返回。

subprocess.run()函数可以运行由参数组成的下令的字符串,而且直到下令完成,在完成后返回一个完成实例。>>> import subprocess>>> subprocess.run("ping -n 1 www.baidu.com", shell=True)正在 Ping www.a.shifen.com [180.97.33.108] 具有 32 字节的数据:来自 180.97.33.108 的回复: 字节=32 时间=33ms TTL=55180.97.33.108 的 Ping 统计信息:数据包: 已发送 = 1,已吸收 = 1,丢失 = 0 (0% 丢失),往返行程的预计时间(以毫秒为单元):最短 = 33ms,最长 = 33ms,平均 = 33msCompletedProcess(args='ping -n 1 www.baidu.com', returncode=0)>>>subprocess.PIPE代表管道是一个特殊的值,使用该值可以将尺度流的管道打开。打开后可以通过sys.stdin获取输入,通过sys.stdout读出输出效果,同时也可以通过sys.stderr获得错误输出。subprocess.Popen()在新历程中执行子法式,在本书中我们将会多次使用该接口,某些场景下我们不需要等候被挪用法式执行完成或返回,只需要将其启动即可。

在预订测试线章节的例子中,我们将使用该接口去启动升级切换法式,启动后无需等候其返回。如果需要等候执行完成,则只需要挪用wait()接口等候其完成即可。import subprocess, osp = subprocess.Popen("dir", cwd=os.getcwd(), shell=True,stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)p.wait()如上面代码中使用的一样,wait()等候子法式竣事。

同时可以设置等候超时时间。更多的细节可以参考如下链接。15.3.10 logging模块logging模块是一个很是好用的日志模块,支持将日志信息显示到尺度输出即常说的串口,也支持将信息生存到日志文件中。

此外该模块也提供了很好的日志分级机制,支持debug,info,warning,error和critical五个级别,该模块会凭据您设置的级别将该级别以上的日志存储到日志中。还可以自界说日志信息的花样,下面的代码片段展示了如何使用日志模块。import logginglogging.basicConfig(level=logging.INFO,format="%(asctime)s %(name)s %(levelname)s %(message)s",datefmt='%Y-%m-%d %H:%M:%S %a',filename='WifiOnlineService.log',filemode='a')logging.debug("WifiOnlineService: %s", '__init__')logging.info("WifiOnlineService: %s", 'isAlive')15.4 代码实现接下来,我们将开始实现详细代码,将思想变为现实。

leyu乐鱼网站登录

15.4.1 编写伪码根据老例,我们首先编写一定的伪码,来资助我们从整体上掌握法式的结构。#使用logging模块界说日志文件及消息结构#实现我们的服务类基于win32serviceutil.ServiceFrameworkclass WifiOnlineService(win32serviceutil.ServiceFramework):#服务名#服务显示名称#服务形貌#实现运行接口def SvcDoRun(self):#详细的服务功效代码实现在这里#实现停止接口def SvcStop(self):#停止服务时需要做到事情都在这里实现if __name__ == '__main__':#挪用servicemanager举行相关的初始化及准备事情#挪用HandleCommandLine接口,使我们的服务支持下令行,好比install/start等参数从我们的伪码可以看出,代码框架比力简朴。

15.4.2 Python代码实现详细的代码实现来了,详细如下,详细功效很简朴就是每3秒ping一次百度。import win32serviceutilimport win32serviceimport win32eventimport win32timezoneimport winerrorimport servicemanagerimport sysimport timefrom subprocess import Popenimport logginglogging.basicConfig(level=logging.INFO,format="%(asctime)s %(name)s %(levelname)s %(message)s",datefmt='%Y-%m-%d %H:%M:%S %a',filename='WifiOnlineService.log',filemode='a')class WifiOnlineService(win32serviceutil.ServiceFramework):# 服务名_svc_name_ = "WifiOnline"# 服务显示名称_svc_display_name_ = "WifiOnline"# 服务形貌_svc_description_ = "Making sure wifi always works"def __init__(self, args):win32serviceutil.ServiceFramework.__init__(self, args)self.eWaitStop = win32event.CreateEvent(None, 0, 0, None)self.isAlive = Truelogging.info("WifiOnlineService: %s", '__init__')def SvcDoRun(self):logging.info("WifiOnlineService: %s", 'SvcDoRun')while self.isAlive:logging.info("WifiOnlineService: %s", 'isAlive')time.sleep(3)Popen("ping -n 1 www.baidu.com", shell=True)def SvcStop(self):logging.info("WifiOnlineService: %s", 'SvcStop')# 先告诉SCM停止这个历程self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)# 设置事件win32event.SetEvent(self.eWaitStop)self.isAlive = Falseif __name__ == '__main__':if len(sys.argv) == 1:# 服务法式应该会先挪用一次初始化logging.info("WifiOnlineService: %s", '1')servicemanager.Initialize()servicemanager.PrepareToHostSingle(WifiOnlineService)servicemanager.StartServiceCtrlDispatcher()else:win32serviceutil.HandleCommandLine(WifiOnlineService)由于服务是运行在后台,看不到摸不着,因此需要通过日志来视察其运行历程。2019-09-06 00:27:16 Fri root INFO WifiOnlineService: 12019-09-06 00:27:16 Fri root INFO WifiOnlineService: __init__2019-09-06 00:27:16 Fri root INFO WifiOnlineService: SvcDoRun2019-09-06 00:27:16 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:19 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:22 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:25 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:28 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:31 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:34 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:37 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:40 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:43 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:46 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:49 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:52 Fri root INFO WifiOnlineService: isAlive2019-09-06 00:27:54 Fri root INFO WifiOnlineService: SvcStop上面的日志显示,先举行的初始化,然后执行了启动服务的操作,运行了一段时间后执行了停止操作。

通过时间戳还可以看出,我们的服务每3秒执行一次ping操作。需要注意的是,我们这里的Python代码需要打包为exe再去做服务的安装和启动。

直接基于Python代码去安装服务的时候没有问题,但当启动服务的时候会有问题。详细原因可以通过日志文件看出来,当我们用Python代码去执行install操作时不会执行if语句中的内容,从而导致启动时有问题,因此建议打包为exe再去操作。或者先不带任何参数,单独执行一次Python代码,然后再带install参数举行安装,再启动服务。

15.4.3 打包为exe举行公布接下来,我们需要将Python代码举行打包,生成exe举行利便使用。将Python代码转换为exe法式,我们使用的是pyinstaller,详细的转换代码我实现为python代码。只需要执行下面的Python代码,就会挪用pyinstaller生成一个单独的exe文件。

这种形式的优点是只有一个exe文件,其他所有的依赖的Python情况文件都被打包在该exe文件中。而缺点就是由此导致该文件比力大,而且每次执行都相当于有一个解压光临时目录的历程,所以执行比力慢。

import os, shutilfrom subprocess import Popenif os.path.exists('dist'):shutil.rmtree("dist")if os.path.exists('build'):shutil.rmtree("build")if os.path.exists('__pycache__'):shutil.rmtree("__pycache__")handle = Popen("pyinstaller -F -w -n wifi_online_service wifi_online_service.py")handle.wait()shutil.copyfile("dist/wifi_online_service.exe", "wifi_online_service.exe")shutil.rmtree("dist")shutil.rmtree("build")shutil.rmtree("__pycache__")小我私家推荐将其打包为目录,而不是单个exe文件。这样的利益就是不需要每次执行都举行解压光临时目录,而是直接在同目录下挪用执行,因此比力快。

而为了更利便,我们这里会先容如何将该目录打包为安装文件,这样在给别人用的时候,只需要给一个安装文件。用户拿到该安装文件后,安装上之后就可以使用了,且使用感受更好。下面就是打包为目录的代码,跟上面有区别,其中一个打包参数为-D。import os, shutilfrom subprocess import Popenif os.path.exists('dist'):shutil.rmtree("dist")if os.path.exists('build'):shutil.rmtree("build")if os.path.exists('__pycache__'):shutil.rmtree("__pycache__")handle = Popen("pyinstaller -D -w -n wifi_online_service wifi_online_service.py")handle.wait()正如上面提到的,我们这里先容一个将目录打包为安装文件的工具法式。

该工具法式名为Inno Setup,是一个免费的工具软件,网站主页如下图8-1所示。可以点击Download Inno Setup链接举行下载,详细信息可以登陆网站()举行相识。图15-1 Inno Setup主页这里,我们要建立服务的安装法式,跟普通的法式安装有点区别。

服务法式在安装完毕后需要安装服务,并启动服务。而普通法式安装完成中,不需要这些分外的操作,因此我们需要对Inno Setup生的iss文件做一些修改。完整的文件如下,大部门是Inno Setup自动生成的,我们这里只是修改[Run]和[UninstallRun]内里的内容,可以参考修改自己的。

在[Run]内里增加的内容是安装完成后,我们的法式执行文件带着参数--startup auto install举行执行一次,然后再带着参数start执行一次,这也就意味着我们的服务被安装为电脑启动的时候自动执行,而且当前也启动了该服务。而[UninstallRun]内里添加的内容意味着,在卸载时先停止服务,再删除服务。

; Script generated by the Inno Setup Script Wizard.; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!#define MyAppName "wifi_online_service"#define MyAppVersion "1.0"#define MyAppPublisher "My Company, Inc."#define MyAppURL "http://www.example.com/"#define MyAppExeName "wifi_online_service.exe"[Setup]; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)AppId={{13993919-2190-41BB-9CD1-2DC8A56671E2}AppName={#MyAppName}AppVersion={#MyAppVersion};AppVerName={#MyAppName} {#MyAppVersion}AppPublisher={#MyAppPublisher}AppPublisherURL={#MyAppURL}AppSupportURL={#MyAppURL}AppUpdatesURL={#MyAppURL}DefaultDirName={autopf}{#MyAppName}DefaultGroupName={#MyAppName}DisableProgramGroupPage=yes; Uncomment the following line to run in non administrative install mode (install for current user only.);PrivilegesRequired=lowestOutputDir=E:实现一个Windows上的服务OutputBaseFilename=wifi_online_service_setupCompression=lzmaSolidCompression=yesWizardStyle=modern[Languages]Name: "english"; MessagesFile: "compiler:Default.isl"[Files]Source: "E:实现一个Windows上的服务distwifi_online_servicewifi_online_service.exe"; DestDir: "{app}"; Flags: ignoreversionSource: "E:实现一个Windows上的服务distwifi_online_service*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs; NOTE: Don't use "Flags: ignoreversion" on any shared system files[Icons]Name: "{group}{#MyAppName}"; Filename: "{app}{#MyAppExeName}"[Run]Filename: "{app}{#MyAppExeName}"; Parameters: "--startup auto install" ; Flags: runhiddenFilename: "{app}{#MyAppExeName}"; Parameters: "start" ; Flags: runhidden[UninstallRun]Filename: "{app}{#MyAppExeName}"; Parameters: "stop" ; Flags: runhiddenFilename: "{app}{#MyAppExeName}"; Parameters: "remove" ; Flags: runhidden这里打包生成的安装文件是一个exe文件,我们双击执行安装时会泛起如图8-2所示界面,可以看出是一个很常见的法式安装界面,跟其他法式安装没有什么区别,看起来更专业。图15-2 服务法式安装界面到这里,法式的打包安装就先容完毕,详细选择哪种方式举行打包,可以凭据详细情况而定。写一个自己的服务法式,举行安装,视察一下日志文件,看看详细发生了什么。

15.5 本章小结本章先容了如何用Python编写一个Windows服务法式,小我私家以为是一个很是有用的功效。可以很容易的将一些需要恒久运行的法式举行改写为服务举行安装,这样就能免去每次开机都需要去手动执行的的贫苦,而且用户也感知不到它的存在。

而且在本章也先容了将Python法式打包为单个exe文件和目录方法及法式,另外也先容了一个免费的Windows打包工具软件Inno Setup,可以利便的用于打包您的法式。该工具不局限于打包Python法式,它可以用于打包任何其他法式,是一个比力好用的工具软件。接待关注,转发,收藏Python实用案例编程入门:第一章 Python概述及为什么学PythonPython实用案例编程入门:第二章 字符串Python实用案例编程入门:第五章 函数和类Python实用案例编程入门:第四章 字典和文件Python实用案例编程入门:第三章 列表和元组Python实用案例编程入门:第七章 调式手段Python实用案例编程入门:第六章 控制流语句Python实用案例编程入门:第十章 用Python处置惩罚音频文件Python实用案例编程入门:第九章 爬虫下载VOA逐日广播英语MP3Python实用案例编程入门:第十二章 测试线预订法式Python实用案例编程入门:第十一章 做一个年会抽奖法式Python实用案例编程入门:第十三章 自动收发电子邮件,远程控制Python实用案例编程入门:第十四章 通过声音控制您的盘算机Python实用案例编程入门:第八章 如何自动毗连WIFI。


本文关键词:leyu,乐鱼,网站,登录,Python,实用,案例,编程,leyu乐鱼全站

本文来源:leyu乐鱼棋牌-www.yybjing.com

leyu乐鱼网站登录_Python实用案例编程入门:第十五章 用Python实现Windows上的服务

本章的主题为用Python实现一个Windows上的服务,我们打开自己电脑上的服务法式,可以看到系统后台启动了许多服务。这些服务在默默的为我们提供了许多功效,可以说我们作为用户,对其看不到摸不着。如果我们也想让自己编写的法式,以服务这种形式在盘算机的后台默默的运行,那该怎么做呢?本章就将围绕这个主题举行学习。...

leyu乐鱼网站登录_Python实用案例编程入门:第十五章 用Python实现Windows上的服务

本章的主题为用Python实现一个Windows上的服务,我们打开自己电脑上的服务法式,可以看到系统后台启动了许多服务。这些服务在默默的为我们提供了许多功效,可以说我们作为用户,对其看不到摸不着。如果我们也想让自己编写的法式,以服务这种形式在盘算机的后台默默的运行,那该怎么做呢?本章就将围绕这个主题举行学习。...

 咨询购买

咨询热线

092-555514828

 在线咨询  在线预约
TOP