Flask+tornado+Nginx+pywin32实现本地网络部署

目录

1.flask程序

2.引入tornado模块

3.部署为Windows Service服务并且开机自启

4.安装Nginx

5.配置Nginx


1.flask程序

编写flask程序,保存为app.py

from flask import Flask, render_template

app = Flask(__name__)
@app.route('/')
def hello_world():  # put application's code here
    user = User(username='名字', email='xxxx@qq.com')
    person = {
        'username': '张三',
        'email': 'zhangsan@qq.com'
    }
    return render_template("index.html", user=user, person=person)

2.引入tornado模块

将app模块一并传入,存储为Service.py

# -*- coding:utf-8 -*-
import asyncio
import inspect
import logging
import os
import socket
import sys
import time
import servicemanager
import win32event
import win32service
import win32serviceutil
import winerror
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.wsgi import WSGIContainer

from app import app


class PythonService(win32serviceutil.ServiceFramework):
    _svc_name_ = 'Flask_Web'  # 属性中的服务名
    _svc_display_name_ = 'FLASK_WEB'  # 服务在windows系统中显示的名称
    _svc_description_ = 'Python的Flask程序,用于验证设置Windows服务,且开机自启'  # 服务的描述


    def __init__(self, args):
        """
        init的内容可以参考以下网址:
            https://www.programcreek.com/python/example/99659/win32serviceutil.ServiceFramework

        :param args:
        """
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.stop_event = win32event.CreateEvent(None, 0, 0, None)
        socket.setdefaulttimeout(60)  # 套接字设置默认超时时间
        self.logger = self._getLogger()  # 获取日志对象
        self.isAlive = True

    def _getLogger(self):
        # 设置日志功能
        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):
        """
        实例化win32serviceutil.ServiceFramework的时候,windows系统会自动调用SvcDoRun方法,
        这个函数的执行不可以结束,因为结束就代表服务停止。
        所以当我们放自己的代码在SvcDoRun函数中执行的时候,必须确保该函数不退出,就需要用死循环

        :return: None
        """
        self.logger.info("服务即将启动...")
        while self.isAlive:
            self.logger.info("服务正在运行...")
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            result = sock.connect_ex(('127.0.0.1', 9900))  # 嗅探网址是否可以访问,成功返回0,出错返回错误码
            if result != 0:
                # Python3.8的asyncio改变了循环方式,因为这种方式在windows上不支持相应的add_reader APIs,
                # 就会抛出NotImplementedError错误。
                # 因此加入下面两行代码
                if sys.platform == 'win32':
                    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
                s = HTTPServer(WSGIContainer(app))
                s.listen(9900)
                IOLoop.current().start()
                time.sleep(8)
            sock.close()
            time.sleep(20)

    def SvcStop(self):
        """
        当停止服务的时候,系统会调用SvcStop函数,该函数通过设置标志位等方式让SvcDoRun函数退出,就是正常的停止服务。
        win32event.SetEvent(self.hWaitStop) 通过事件退出

        :return: None
        """
        self.logger.info("服务即将关闭...")
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)  # 先告诉SCM停止这个过程
        win32event.SetEvent(self.stop_event)  # 设置事件
        self.ReportServiceStatus(win32service.SERVICE_STOPPED)  # 确保停止,也可不加
        self.isAlive = False


if __name__ == '__main__':
    print("接收到的参数为", sys.argv)
    if len(sys.argv) == 1:
        print("输入参数不正确!")
        try:
            evtsrc_dll = os.path.abspath(servicemanager.__file__)
            servicemanager.PrepareToHostSingle(PythonService)
            servicemanager.Initialize('PythonService', evtsrc_dll)
            servicemanager.StartServiceCtrlDispatcher()
        except Exception as details:
            print("发生异常,信息如下:", details)
            # 如果错误的状态码为1063,则输出使用信息
            if details[0] == winerror.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
                win32serviceutil.usage()
    else:
        win32serviceutil.HandleCommandLine(PythonService)  # 括号里必须与class类名一致

3.部署为Windows Service服务并且开机自启

常用的服务命令主要有以下几种,首先安装服务,其次运行服务,在服务列表里,看到服务正在运行。在安装的过程中可能存在无法启动的异常,需要在系统变量的path变量中新建C:\Python\Python310\lib\site-packages\pywin32_system32,然后重新安装,启动。在浏览器中访问127.0.0.1:9900,出现相关页面,即可进行下一步

# 1.安装服务
python PythonService.py install
# 2.以开机自启的方式安装服务
python PythonService.py --startup auto install
# 3.启动服务
python PythonService.py start
# 4.重启服务
python PythonService.py restart
# 5.停止服务
python PythonService.py stop
# 6.删除/卸载服务
python PythonService.py remove

4.安装Nginx

从相关网站下载window版本的Nginx压缩包,解压到指定目录,双击exe文件启动Nginx,此时访问127.0.0.1出现欢迎揭界面,代表Nginx运行成功。

5.配置Nginx

修改D:\nginx-1.22.1\conf目录下的nginx.conf文件,添加一句话即可,保存后重启Nginx,在浏览器中访问localhost出现flask项目视图,完成。

proxy_pass  http://localhost:9900;  # 加上这句

server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
            proxy_pass  http://localhost:9900;  # 加上这句

        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值