我正在寻找有关如何实现函数启动/停止功能的指导,这使得restAPI
能够通过{{1}点击呈现的html页面上的按钮,连续地检索JSON格式的数据并托管在GAE上?
当前行为是一旦http请求完成,被调用的函数当然会停止(webapp2
)(根据GAE文档的正常行为)。
main.py:
while self._running == True
page.html:
#!/usr/bin/env python
#
import webapp2
from google.appengine.api import urlfetch
from matplotlib.path import Path as mpPath
import json
import base64
import socket
import logging
from threading import Thread
import jinja2
template_dir = os.path.join(os.path.dirname(__file__))
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir),
extensions=['jinja2.ext.autoescape'], autoescape=True)
# create a UDP socket for sending the commands
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
# create the stop / start functionality of a thread that runs infinite until
# thread is terminated
class CMX:
def __init__(self):
self._running = True
def terminate(self):
self._running = False
def run(self):
storedCredentials = False
username = None
password = None
ip_address = 'someip' # commands are send to the broadcast address for addressing the zones(bays)
port = someport # use of port 50011 because no return packet is send back, could cause the
# lights not to execute the command when using broadcast.
# define the boundaries of the different zones
zone = [[(106.03,141.19),(158.94,141.19),(158.94,194.50),(106.03,194.50)],
[(103.76,168),(62.26,168),(62.26,77.86),(103.67,77.86)],
[(106.38,77.86),(191.95,77.86),(191.95,106.52),(106.38,106.52)]]
flag_zone_1 = False
flag_zone_2 = False
flag_zone_3 = False
while self._running == True:
restURL = 'http://someurl'
print restURL
if not storedCredentials:
username = 'username'
password = 'password'
storedCredentials = True
try:
request = urlfetch.fetch(url = restURL, headers={"Authorization": "Basic %s" % base64.b64encode(username +':'+ password)})
<perform actions and other function calls>
.
.
except urlfetch.Error:
logging.exception('Caught exception fetching url')
class Handler(webapp2.RequestHandler):
def write(self, *a, **kw):
self.response.out.write(*a, **kw)
def render_str(self, template, **params):
t = jinja_env.get_template(template)
return t.render(params)
def render(self, template, **kw):
self.write(self.render_str(template, **kw))
class MainPage(Handler):
def get(self):
button = "Start Demo"
running = False
self.render('page.html', button = button, run = running)
def post(self):
startDemo = CMX()
t = Thread(target=startDemo.run, args=())
t.daemon = True
if self.request.get('button') == "Start Demo":
button = "Stop Demo"
running = True
self.render('page.html', button = button, run = running)
t.start()
else:
button = "Start Demo"
running = False
self.render('page.html', button = button, run = running)
startDemo.terminate()
def which_zone(xcoord, ycoord, zone):
point = (xcoord, ycoord)
in_zone_1 = mpPath(zone[0]).contains_point(point)
in_zone_2 = mpPath(zone[1]).contains_point(point)
in_zone_3 = mpPath(zone[2]).contains_point(point)
if in_zone_1 == True:
return "Zone 1"
elif in_zone_2 == True:
return "Zone 2"
elif in_zone_3 == True:
return "Zone 3"
def dim_lights(ip_address, port, control_string, sock):
control_string = control_string + 'S0F10' +'\r'
#sock.sendto(control_string, (ip_address, port))
return control_string
def norm_lights(ip_address, port, control_string, sock):
control_string = control_string + 'S255F10' +'\r'
#sock.sendto(control_string, (ip_address, port))
return control_string
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
答案 0 :(得分:0)
启动/停止功能很简单 - 只需使按钮控制类似operation_is_stopped
标记,例如在数据存储区中保留(例如)。
如果您没有意识到这一点,那么您的难度实际上来自于您希望使用该按钮控制的连续操作。这与GAE并不完全兼容 - GAE中的所有内容都围绕响应请求,在有限的时间内。你无法在GAE中真正拥有无限期运行的程序/线程。
但在许多情况下,可以将长时间运行的迭代连续操作(与您的一样)实现为短期操作流。在使用task queues可以轻松实现的GAE中 - 每次迭代(在您的情况下,while self._running == True
循环的主体)都实现为对任务队列请求的响应。
当触发“开始”操作时,通过将相应任务排队来启动流程。通过在处理先前任务请求之后使相应任务入队来维持该流程。它被不排队新任务所阻止:)
这些方面的东西:
def post(self): # handler for the "long running" task requests
# need to rebuild/restore your request context every time
...
try:
request = urlfetch.fetch(...)
<perform actions and other function calls>
except:
...
finally:
if not operation_is_stopped:
# enqueue another "long running" task
task = taskqueue.add(...)