调用Twisted recator.run()在烧瓶app里面

时间:2016-08-19 15:09:23

标签: python python-2.7 flask twisted jasmin-sms

我正在python flask中为Jasmin SMS Gateway编写一个Web服务,以便从网关创建和删除用户。在POST请求的情况下,我调用runScenario(),然后我启动reactor.run(),它将在网关中创建用户。这段代码完全适用于第一个Web服务调用,但在第二次调用时它给了我这个错误:

raise error.ReactorNotRestartable()
ReactorNotRestartable

这是我的Flask应用程序:

#!/usr/bin/env python
from flask import Flask, jsonify, request, Response, make_response, abort
from JasminIntegration import *

JasminWebservice = Flask(__name__)

@JasminWebservice.errorhandler(404)
def not_found(error):
    return make_response(jsonify({'error': 'Not found'}), 404)

@JasminWebservice.route('/jsms/webservice', methods=['POST'])
def create_user():
    if not request.json or not 'username' in request.json:
        abort(400)

    runScenario(request)
    reactor.run()
    return jsonify({'response':'Success'}), 201

if __name__ == '__main__':    
    JasminWebservice.run(host="0.0.0.0",port=7034,debug=True)

我正在调用在JasminIntegration.py

中定义的runScenario()
#!/usr/bin/env python
import sys
import pickle
from flask import abort
from twisted.internet import defer, reactor
from jasmin.managers.proxies import SMPPClientManagerPBProxy
from jasmin.routing.proxies import RouterPBProxy
from jasmin.routing.Routes import DefaultRoute
from jasmin.routing.jasminApi import SmppClientConnector, User, Group, MtMessagingCredential, SmppsCredential
from jasmin.protocols.smpp.configs import SMPPClientConfig
from twisted.web.client import getPage


@defer.inlineCallbacks
def runScenario(Request):
    try:
        proxy_router = RouterPBProxy()
        yield proxy_router.connect('127.0.0.1', 8988, 'radmin', 'rpwd')

        if Request.method == 'POST':            
            smppUser = Request.json['username']
            smppPass = Request.json['password']
            smppThroughput = Request.json['tp']
            smppBindSessions = Request.json['sessions']

            if not smppUser:
                abort(400)

            if len(smppPass) == 0 or len(smppPass) > 8:
                abort(400)

            if not smppThroughput.isdigit():
                abort(400)

            if not smppBindSessions.isdigit():
                abort(400)

            # Provisiong router with users
            smpp_cred = SmppsCredential()
            yield smpp_cred.setQuota('max_bindings',int(smppBindSessions))

            mt_cred = MtMessagingCredential()
            yield mt_cred.setQuota('smpps_throughput' , smppThroughput)
            #yield mt_cred.setQuota('submit_sm_count' , 500)

            g1 = Group('clients')
            u1 = User(uid = smppUser, group = g1, username = smppUser, password = smppPass, mt_credential = mt_cred, smpps_credential = smpp_cred)
            yield proxy_router.group_add(g1)
            yield proxy_router.user_add(u1)

        if Request.method == 'DELETE':

            smppUser = Request.json['username']

            if not smppUser:
                abort(404)

            yield proxy_router.user_remove(smppUser) 
    except Exception, e:
        yield "%s" %str(e)

    finally:
        print "Stopping Reactor"
        reactor.stop()

请帮我解决这个问题:

3 个答案:

答案 0 :(得分:1)

Reactor在Twisted设计中无法重启,它执行的初始化和终结不容易重启。

在提供的示例中,您使用的是开发WSGI服务器(烧瓶的默认值http://werkzeug.pocoo.org/docs/0.11/serving/),默认情况下它似乎是单线程的。

如果您避免使用线程并切换到多进程服务器,那么您的问题就会消失。 即如果你只是像这样运行它会起作用(参见 processes = 2 =>每个请求将在一个新进程中处理,但不超过2个并发):

if __name__ == '__main__':                                                      
    JasminWebservice.run(host="0.0.0.0", port=7034, debug=True, processes=2)

但是我不会依赖于此 - 在编写单元测试时你会遇到类似的麻烦,限制你的应用程序在多进程环境中运行只是不是一件好事做法。

但看起来问题源于你的应用程序设计 - 为什么你需要Flask和一个额外的WSGI服务器? 您可以完全构建REST API,最终只运行一个单独的反应器,该反应器将处理对API和传入请求的查询。

答案 1 :(得分:0)

您无法停止反应堆并再次运行它。你得到的错误是设计的。考虑使用kleinwerkzeug使用flasktwisted,并利用klein进行联网。语法甚至类似。将代码翻译成import json from klein import Klein from exception werkzeug.exceptions import NotFound from JasminIntegration import * JasminWebservice = Klein() @JasminWebservice.handle_errors(NotFound) def not_found(request, error): request.setResponseCode(404) return json.dumps({'error': 'Not found'}) @JasminWebservice.route('/jsms/webservice', methods=['POST']) def create_user(request): try: data = json.loads(request.content.read()) if not data or if 'username' not in data: raise NotFound() except: # yeah I know this isn't best practice raise NotFound() runScenario(request) request.setResponseCode(201) return json.dumps({'response':'Success'}) if __name__ == '__main__': JasminWebservice.run("0.0.0.0", port=7034) 看起来有点像这样:

reactor

作为旁注,除非您想要完全退出应用,否则不应停止1,6,1,0 2,3,0,0 3,2,0,0 my $filename = $ARGV[0]; open(my $filehandle, '<', $filename) or die "Could not open $filename\n"; # my @resultarray; while(my $line = <$filehandle>){ my @linearray = split("/n", $line); } while(foreach(@linearray){ my @resultarray = split(",", $linearray); }

答案 2 :(得分:0)

@ffeast我也尝试过扭曲但遇到同样的问题,因为reactor不能重启。在扭曲中我做了类似的事情:

int totalamountofcandies = 0;
for (int i=0;i<100;i++) {
    int grosstotalcandies = currentcandies + currentamountofpokemon;
    int howmanycanevolve = grosstotalcandies / howmanycandiestoevolve;
    totalamountofcandies += howmanycanevolve + grosstotalcandies;
}