Google App Engine, запуск / остановка непрерывного сценария при нажатии кнопки

Я ищу руководство для достижения функции запуска / остановки функции, которая делает restAPI для restAPI извлечения данных в формате JSON, нажатием кнопки на отображаемой странице html через webapp2 и размещением на GAE?

Текущее поведение после завершения HTTP-запроса завершается функцией, которая была вызвана, конечно, останавливается (в while self._running == True ) (нормальное поведение в соответствии с документацией GAE).

main.py:

 #!/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) 

page.html:

 {% extends "base.html" %} {% block comment %} {% autoescape true %} <form method="post"> <div> <input type="submit" name="button" value="{{button}}"> <input type="hidden" name="run" value="{{run}}"> </div> <!-- <div>macAddress: <input type="text" name="macAddress"><br> <input type="submit" value="Submit"> </div> --> </form> {% endautoescape %} {% endblock %} 

One Solution collect form web for “Google App Engine, запуск / остановка непрерывного сценария при нажатии кнопки”

Функция запуска / остановки проста – просто сделайте кнопку управления чем-то вроде флага operation_is_stopped сохраняется в запросах (например, в хранилище данных).

В случае, если вы этого не осознали, ваша трудность действительно связана с достижением непрерывной операции, которую вы хотите контролировать с помощью этой кнопки. Это то, что на самом деле не совместимо с GAE – все в GAE вращается вокруг ответа на запросы в течение ограниченного времени . Вы действительно не можете бесконечно запускать процессы / потоки в GAE.

Но во многих случаях можно реализовать длительную итеративную непрерывную операцию (например, ваш) как поток короткоживущих операций. В GAE, который может быть легко достигнут с помощью очередей задач – каждая итерация (в вашем случае тело while self._running == True loop) реализована как ответ на запрос очереди задач.

Поток запускается путем постановки на охрану соответствующей задачи при срабатывании «запуска». Поток поддерживается путем задания соответствующей задачи после обработки предыдущего запроса задачи. И он остановлен, не ставя в очередь новую задачу 🙂

Что-то в этом роде:

 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(...) 
  • Django 1.7 в App Engine "ImportError: нет модуля с именем msvcrt"
  • DockerDaemonConnectionError при настройке виртуальной виртуальной машины Google Cloud в Ubuntu
  • Запуск, остановка и продолжение работы с BulkLoader в Google App Engine
  • Как использовать очередь задач App Engine с помощью вычисления экземпляра двигателя
  • Смешивание python с более быстрым языком для оптимизации в GAE
  • Resident Backend Google App Engine "/ _ah / background" (Python)
  • Имя текущего приложения в Google App Engine (Python)
  • GAE "no attribute" HTTPSHandler "" dev_appserver.py
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.