使用Twisted更新共享数据

4 投票
1 回答
2279 浏览
提问于 2025-04-16 16:58

我想知道如何使用Twisted服务器分享一块数据,同时在后台定期更新这块数据:

from twisted.internet import reactor
from twisted.internet import task
from twisted.web.server import Site
from twisted.web.resource import Resource

data = 1

def update_data():
    data += 1

class DataPage(Resource):
    isLeaf = True
    def render_GET(self, request):
        return "<html><body>%s</body></html>" % (data, )

root = Resource()
root.putChild("data", DataPage())
factory = Site(root)
reactor.listenTCP(8880, factory)

m = task.LoopingCall(update_data)
m.start(10.0)

print "running"
reactor.run()

上面的代码不工作,出现了以下错误:

C:\temp>python discovery.py
Unhandled error in Deferred:
Traceback (most recent call last):
  File "discovery.py", line 23, in <module>
    m.start(10.0)
  File "c:\python25\lib\site-packages\twisted\internet\task.py", line 163, in start
    self()
  File "c:\python25\lib\site-packages\twisted\internet\task.py", line 194, in __call__
    d = defer.maybeDeferred(self.f, *self.a, **self.kw)
--- <exception caught here> ---
  File "c:\python25\lib\site-packages\twisted\internet\defer.py", line 102, in maybeDeferred
    result = f(*args, **kw)
  File "discovery.py", line 10, in update_data
    data += 1
exceptions.UnboundLocalError: local variable 'data' referenced before assignment

我希望HTTP客户端可以访问这个链接,http://127.0.0.1:8880/data,并获取当前的数据值。同时,我还想安排其他任务,定期更新这些数据。

而且,我其实不太想用LoopingCall(),因为我可能想根据更新是否成功来调整更新的间隔;这个更新会是某种远程API调用。我可以用CallLater()来实现吗?

我知道这个问题可能很傻!谢谢大家。

编辑:这个方法帮助我正确地将数据变量设为全局变量。对于后续的人,这里是如何将callLater()融入代码中的:

from twisted.internet import reactor
from twisted.internet import task
from twisted.web.server import Site
from twisted.web.resource import Resource

data = 1

def update_data():
    global data
    data += 1
    reactor.callLater(10, update_data)

class DataPage(Resource):
    isLeaf = True
    def render_GET(self, request):
        return "<html><body>%s</body></html>" % (data, )

root = Resource()
root.putChild("data", DataPage())
factory = Site(root)
reactor.listenTCP(8880, factory)

update_data()

print "running"
reactor.run()

这段代码还是感觉有点不太好。我不喜欢声明模块级变量,更不想用全局变量。我欢迎任何建议,避免这种做法,让代码看起来更整洁、更易于重用。

1 个回答

3

添加一个全局的函数,名字叫 update_data():

def update_data():
    global data
    data += 1

撰写回答