简体   繁体   中英

How to run 2 servers from the same script in Python

I'm building a solution that depends on pub/sub events from IOT devices in the field to kick off some processing. For my purposes, I'm using Flask as to run my main app. I then run the mqtt Client to connect to an MQTT server and listen for events.

When I run my main Flask app.py using python app.py it starts both the Flask service and the MQTT Client. However, when I try to run with gunicorn, it only starts the the Flask service but does not start the MQTT Client.

What production grade service (if not gunicorn) can I use to have both these two services run and how to use it?

import logging, json, requests, os
import paho.mqtt.client as mqtt

from flask import Flask, request, url_for
from flask_restful import reqparse, abort, Api, Resource
from logging.handlers import SysLogHandler
from logging import StreamHandler
from flask.ext.superadmin import Admin, BaseView, model
from redis import Redis
from rq import Queue
from task import Task
from dateutil.relativedelta import relativedelta
from datetime import datetime, date
..
..
from commons import db, bootstrap

app = Flask(__name__)
api = Api(app)

bootstrap.bootstrap_app(app)

#Setup (Redis) Queue store
q = Queue(connection=Redis())

#Intialize task instance
task = Task(app)
..
...
@app.before_request
def log_request_info():
    app.logger.debug('Headers: %s', request.headers)
    app.logger.debug('Body: %s', request.get_data())

#API resource routing
api.add_resource(Test, '/test')


def session_report(client, userdata, message):
    print message.topic, message.payload

    # Redirect to session_report endpoint
    with app.test_request_context():
        url = 'http://localhost:5000'+url_for('sessionreport', _external=False)
        headers = {'content-type': 'application/json'}
        response = requests.request("POST", url, data=message.payload, 
            headers=headers)

def process_ack(client, userdata, message):
    try:
        user = User()
        user.update_account(account_number=next(iter(json.loads(message.payload))))
    except Exception, e:
        print e

def publish_accounts(client):
    user_obj = User()
    users = {user.id: user.account_number for user in user_obj.get_users()}
    client.publish('accounts', payload=json.dumps(users), qos=1, retain=True)


# paho callbacks

def on_connect(client, userdata, flags, rc):
    print "CONNECTED!", str(rc)

    # Subscribe to topis(s) here
    client.subscribe("mine/#")
    client.subscribe("session/#")
    client.subscribe("ack")

    # Add callbacks to subscribed topics
    client.message_callback_add("session/#", session_report)
    client.message_callback_add("ack", process_ack)

    # Publish latest list of accounts
    publish_accounts(client)

def on_subscribe(client, userdata, mid, granted_qos):
    print "Subscribed: ", str(mid), str(granted_qos)

def on_message(client, userdata, msg):
    print msg.topic, msg.payload

def on_publish(client, userdata, mid):
    print "PUBLISHED!"
    app.logger.info('PUBLISHED : {} -- {}'.format(mid, userdata))


if __name__ == '__main__':
    handler = StreamHandler()   #SysLogHandler()
    handler.setLevel(logging.DEBUG)
    app.logger.addHandler(handler)  
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_subscribe = on_subscribe
    client.on_message = on_message
    client.connect("localhost", 1883, 60)
    client.loop_start()
    app.run(debug=True, host='0.0.0.0', port=5000)

Flask is just a microframework for Python. if you want to run multi-method at the same time by python, you need to use multi-threading programming.

I read some more Flask document and found that Flask supports multithreaded concurrency.

just try:

app.run(host='0.0.0.0',port=5000,debug=True, threaded = True)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM