这几天我用Python做了一个PDF转JPG的工具,转的速度极快,比较推荐使用。
做好工具后,想做成服务,于是我就在网上开始找资料,最后我自己成功开发并发布一个Python的Windows Service。
先来个小型的服务,基本没有什么功能的,只具备写几行日志的功能。
_svc开头的是系统的约定,是不能修改的。
Svc开头的方法也是系统的约定,也是不能修改的。
#-*- coding:utf-8 -*-
import win32serviceutil
import win32service
import win32event
class PythonService(win32serviceutil.ServiceFramework):
_svc_name_="PythonService"
_svc_display_name_="Python Service Demo"
_svc_description="Python service demo"
def __init__(self,args):
win32serviceutil.ServiceFramework.__init__(self,args)
self.hWaitStop =win32event.CreateEvent(None,0,0,None)
self.logger=self._getLogger()
self.isAlive=True
def _getLogger(self):
import logging
import os
import inspect
logger=logging.getLogger('[PythonService]')
this_file =inspect.getfile(inspect.currentframe())
dirpath=os.path.abspath(os.path.dirname(this_file))
handler=logging.FileHandler(os.path.join(dirpath,"service.log"))
formatter = logging.Formatter(
'%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
return logger
def SvcDoRun(self):
import time
self.logger.error("svc do run...")
while self.isAlive:
self.logger.error("I am alive.")
time.sleep(1)
def SvcStop(self):
self.logger.error("svc do stop...")
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
self.isAlive=False
if __name__=='__main__':
win32serviceutil.HandleCommandLine(PythonService)
开发服务记得要安装pywin32,用pip install pywin32 进行安装
写好代码后,有两种安装方法:
第一种基于源码的:python 源码完整路径名称.py 命令
命令解释: install 安装。强调下,一定要在管理员的方式下CMD进行。
start 启动,如果启动不起来,把C:Program FilesPython39Scripts;C:Program FilesPython39Libsite-packagespywin32_system32;这个路径配置到系统的Path中,并且不要使用默认的本地系统账号,用一个有管理员权限的账号。
stop 停止,如果停止不了,在任务管理器中找到PythonService,然后强行结束
update 更新,在源码有修改的时候要先update
第二种基于部署包的:
先安装pyinstaller,用pip install pyinstaller
然后用 pyinstall -F -c 源码完整路径.py ,系统会在当前目录下生成一个子目录dist和同名的exe文件
安装:
exe文件 命令
命令解释同上。
完整的一个服务的源码如下:
#-*- coding:utf-8 -*-
#要安装pywin32
import win32serviceutil
import win32service
import win32event
import win32timezone
from pdf2image import convert_from_path
from pathlib import Path
from os import listdir
from PIL import Image
import os
import time
from shutil import copyfile
import shutil
class PythonService(win32serviceutil.ServiceFramework):
_svc_name_ = "PythonService PDF2JPG"
_svc_display_name_ = "Python Service PDF2JPG"
_svc_description = "Python service PDF2JPG"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
self.logger = self._getLogger()
self.isAlive = True
self.path_to_watch = "D:\PDFS"
def _getLogger(self):
import logging
import os
import inspect
logger = logging.getLogger('[PythonService_PDF2JPG]')
this_file = inspect.getfile(inspect.currentframe())
dirpath = os.path.abspath(os.path.dirname(this_file))
handler = logging.FileHandler(os.path.join(
dirpath, "pythonservice_pdf2jpg.log"))
formatter = logging.Formatter(
'%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
return logger
def pdf_to_image(self, pdf_filename):
#判断路径是否存在
#if not pdf_filename.upper().endswith(".PDF"):
# return
#print('处理 pdf_filename:', pdf_filename)
self.logger.info("Process File:"+pdf_filename)
filename_withoutext = pdf_filename.split('.')[0]
out_path = Path(filename_withoutext)
#print('out_path', out_path)
out_path_full = os.path.join(self.path_to_watch, out_path)
out_path_full_trim = out_path_full.strip()
#print('完整路径:', out_path_full)
self.logger.info("out_path_full:"+out_path_full_trim)
out_path_full_check = Path(out_path_full_trim)
if out_path_full_check.exists():
self.logger.info("path exist")
#shutil.rmtree(out_path_full)
#self.logger.info("path delete")
if not out_path_full_check.exists():
#print('创建目录:', out_path_full)
self.logger.info("not exist,to create")
os.mkdir(out_path_full_trim)
#print('开始转换')
pdf_filename = os.path.join(self.path_to_watch, pdf_filename)
self.logger.info("pdf_filename:"+pdf_filename)
#print('filename:', pdf_filename)
pages = convert_from_path(pdf_filename, dpi=400, output_folder=None, fmt="JPEG",
thread_count=1)
self.logger.info("pages count:"+str(len(pages)))
pindex = 1
for p in pages:
p_f = os.path.join(out_path_full_trim, str(pindex)+'.jpg')
p.save(p_f)
pindex = pindex+1
time.sleep(1)
#print('转换完成')
self.logger.info("convert end")
self.contact_image(out_path_full)
#print('合并完成')
path_file = pdf_filename.split('.')[0]
sub_path = os.path.join(self.path_to_watch, path_file).strip()
#print('删除目录', sub_path)
shutil.rmtree(sub_path)
self.logger.info("delete path:"+sub_path)
def open_image(self, out_path_full, fn):
image_file = os.path.join(out_path_full, fn)
#print('打开图片路径', image_file)
return Image.open(image_file)
def contact_image(self, out_path_full):
#print('开始合并')
#print('合并路径:', out_path_full)
out_path_full_trim = out_path_full.strip()
image_list = [self.open_image(out_path_full_trim, fn)
for fn in listdir(out_path_full_trim) if fn.endswith('.jpg')]
#print('图片数量:', len(image_list))
images = []
width = 0
height = 0
total_height = 0
max_width = 0
for i in image_list:
if i.size[0] > width or i.size[1] > height:
width, height = i.size
#print('width %d,height %d ' % (width, height))
if height >
new_image = i.resize((1102, 1564), Image.BILINEAR) # 551*782
images.append(new_image)
total_height = total_height+1564
max_width = 1102
else:
new_image = i.resize((1102, 776), Image.BILINEAR) # 551*782
images.append(new_image)
total_height = total_height+776
max_width = 1102
result = Image.new(
images[0].mode, (max_width, total_height), "white")
#print('total_height:', total_height)
save_path = out_path_full+".jpg"
#copy_to=out_path_full+".swf"
#print('save path:', save_path)
height_total = 0
for i, im in enumerate(images):
height_im = im.size[1]
#print('height_im %d' % height_im)
result.paste(im, box=(0, height_total))
result.save(save_path)
height_total = height_total+height_im
#copyfile(save_path,copy_to)
def service(self):
pdf_files = dict([(f, None) for f in os.listdir(
self.path_to_watch) if f.upper().endswith('.PDF')])
for f in pdf_files:
f_full = os.path.join(self.path_to_watch, f)
f_jpg = f.split('.')[0]+'.jpg'
f_jpg_full = os.path.join(self.path_to_watch, f_jpg)
#self.logger.info(msg="PDF File:"+f_full)
#self.logger.info(msg="JPG File:"+f_jpg_full)
#print(f_jpg_full)
f_jpg_full_check = Path(f_jpg_full)
if not f_jpg_full_check.exists():
self.logger.info(msg="Not found JPG File:"+f_jpg_full)
#print(f_full)
#time.sleep(1)
#self.logger.info(msg="Add File:"+f_full)
#print('文件名:', f_full)
self.pdf_to_image(f)
self.logger.info(msg="[OK]Add File:"+f_full)
def SvcDoRun(self):
import time
self.logger.info("Service Start...")
self.logger.info("Monitor Path:"+self.path_to_watch)
while self.isAlive:
try:
self.logger.info(msg="Doing...")
self.service()
time.sleep(3)
except Exception as e:
self.logger.error("Error Info:"+e)
time.sleep(10)
def SvcStop(self):
self.logger.info("Service Stop...")
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
self.isAlive = False
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(PythonService)