Sanic: Access global variable from route def

Created on 30 Aug 2018  ·  4Comments  ·  Source: sanic-org/sanic

Hello,

I want to access updated global variable (mytime) in def.
I can access but first created value.
Is there a way todo it?

Regards

from sanic import Sanic
from sanic import response
import time
import threading


app = Sanic(__name__)

mytime=0

def updateTime():
    global mytime
    mytime = int(round(time.time() * 1000))
    print("updateTime",mytime)
    threading.Timer(1, updateTime).start()

updateTime()


@app.route("/")
async def test(request):
    return response.json({"test": True, "mytime":mytime})


if __name__ == '__main__':
    app.run(host="0.0.0.0", port=8080, workers=2)

Most helpful comment

I think it's all about the threads, I would not use them in an asynchronous Sanic.
Try it:

import asyncio

class MyTimeManager(Singleton):
    _mytime = 0

    def start(self):
        @app.listener("after_server_start")
        async def on_server_start(app, loop):
            asyncio.ensure_future(MyTimeManager().updateTime(), loop=loop)

    async def updateTime(self):
        while True:
            await asyncio.sleep(1.0)
            self._mytime = ...

    @property
    def mytime(self):
        return self._mytime

app = Sanic(__name__)
MyTimeManager().start()

...

All 4 comments

Hi!
Try to use Singleton pattern instead of using global variables. Like this:

class Singleton(object):
    _instance = None

    def __new__(class_, *args, **kwargs):
        if not isinstance(class_._instance, class_):
            class_._instance = object.__new__(class_, *args, **kwargs)
        return class_._instance

class MyTimeManager(Singleton):
    _mytime = 0

    def updateTime(self):
        self._mytime = int(round(time.time() * 1000))
    print("updateTime", self._mytime)
    threading.Timer(1, self.updateTime).start()

    @property
    def mytime(self):
        return self._mytime

app = Sanic(__name__)
MyTimeManager().updateTime()

@app.route("/")
async def test(request):
    return response.json({"test": True, "mytime": MyTimeManager().mytime})


if __name__ == '__main__':
    app.run(host="0.0.0.0", port=8080, workers=2)

Hello,

Thank you very much for your reply but it is still response first setted time value not updating.
I added testtime to response. testtime is updating but mytime not.

@app.route("/")
async def test(request):
    testtime=int(round(time.time() * 1000))
    return response.json({"test": testtime, "mytime": MyTimeManager().mytime})

I think it's all about the threads, I would not use them in an asynchronous Sanic.
Try it:

import asyncio

class MyTimeManager(Singleton):
    _mytime = 0

    def start(self):
        @app.listener("after_server_start")
        async def on_server_start(app, loop):
            asyncio.ensure_future(MyTimeManager().updateTime(), loop=loop)

    async def updateTime(self):
        while True:
            await asyncio.sleep(1.0)
            self._mytime = ...

    @property
    def mytime(self):
        return self._mytime

app = Sanic(__name__)
MyTimeManager().start()

...

Thank you very much it is ok now.

Best Regards

Was this page helpful?
0 / 5 - 0 ratings