Search code examples
pythoncherrypy

How to exec periodically a function in CherryPy


This code generate 3 webpages using CheryPy. It's works but now i need to execute periodically the function "PageWeb" to have last informations from a query. How to use threading in CherryPy:

from Widget import showLine
from Widget import SocketLivestatus
import cherrypy
import threading


def PageWeb(cluster):
    # Open Socket
    table = SocketLivestatus(['host1','host2'], 50000, cluster)
    # Result
    Line = showLine(table) 
    HTML = '''<!doctype html>
             <html lang="en">
                <head><meta charset="utf-8">
                 <title>Widget</title>
                 <link rel="stylesheet" href="css/font-awesome.min.css">
             </head>
            <body style="background-color: #1F1F1F">'''+Line+'''</body>
            </html>'''
    return HTML

#BEFORE
re7 = PageWeb("re7")
prod1 = PageWeb("prod1")
prod2 = PageWeb("prod2")
#MY GOAL
re7 = threading.Timer(5.0, PageWeb("re7")).start()
prod1 = threading.Timer(5.0, PageWeb("prod1")).start()
prod2 = threading.Timer(5.0, PageWeb("prod2")).start()


class HelloWorld(object):
    @cherrypy.expose
    def re7(self):
        return re7

    @cherrypy.expose
    def prod1(self):
        return prod1

    @cherrypy.expose
    def prod2(self):
        return prod2



if __name__ == '__main__':
   cherrypy.config.update(
    {'server.socket_host': '0.0.0.0'} )
   cherrypy.quickstart(HelloWorld(),config={
        '/':
        { 'tools.staticdir.on':True,
          'tools.staticdir.dir': "/app"
        }
       # '/fonts':
       # { 'tools.staticdir.on':True,
       #   'tools.staticdir.dir': "/app"
       # }  
    })

The problem is about threading.Timer(5.0, PageWeb("...")).start() return an error:

Traceback (most recent call last):
  File "/usr/lib64/python2.7/threading.py", line 811, in __bootstrap_inner
    self.run()
  File "/usr/lib64/python2.7/threading.py", line 1083, in run
    self.function(*self.args, **self.kwargs)
TypeError: 'str' object is not callable

I would like help to use threading function in CherryPy.


Solution

  • A threading.Timer only runs once:

    This class represents an action that should be run only after a certain amount of time has passed

    After some experimentation, it appears that cherrypy does not work well with threads. The following code uses the multiprocessing library to create a separate Process. The HTML is shared by storing it as the first entry of a managed list:

    import cherrypy
    import multiprocessing
    import time
    
    def PageWeb(cluster, sleep_interval, lock, shared_result):
        counter = 0
        while True:
            HTML = '''<!doctype html>
                     <html lang="en">
                        <head><meta charset="utf-8">
                         <title>Widget</title>
                         <link rel="stylesheet" href="css/font-awesome.min.css">
                     </head>
                    <body style="background-color: #1F1F1F">'''+str(counter)+'''</body>
                    </html>'''
            counter += 1
            with lock:
                shared_result[0] = HTML
            time.sleep(sleep_interval)
    
    class HelloWorld(object):
        def __init__(self):
            self.re7_lock = multiprocessing.Lock()
            self.manager = multiprocessing.Manager()
            self.re7_result = self.manager.list()
            self.re7_result.append('')
            arg_list = ("re7", 5.0, self.re7_lock, self.re7_result)
            self.re7_process = multiprocessing.Process(target=PageWeb, args=arg_list)
            self.re7_process.daemon = True
            self.re7_process.start()
    
        @cherrypy.expose
        def re7(self):
            with self.re7_lock:
                return str(self.re7_result[0])
    
    cherrypy.quickstart(HelloWorld())
    

    This code is a minimal, complete, and verifiable example. You should be able to integrate it with your code.