zoukankan      html  css  js  c++  java
  • Python-Serivce的开发和遇到的坑

    这几天我用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)
    

      

  • 相关阅读:
    Python元组、列表、字典
    测试通过Word直接发布博文
    Python环境搭建(windows)
    hdu 4003 Find Metal Mineral 树形DP
    poj 1986 Distance Queries LCA
    poj 1470 Closest Common Ancestors LCA
    poj 1330 Nearest Common Ancestors LCA
    hdu 3046 Pleasant sheep and big big wolf 最小割
    poj 3281 Dining 最大流
    zoj 2760 How Many Shortest Path 最大流
  • 原文地址:https://www.cnblogs.com/xiaoyichong/p/14301049.html
Copyright © 2011-2022 走看看