使用 Twisted 更新共享数据

发布于 2024-11-04 17:27:07 字数 2372 浏览 1 评论 0原文

如何使用 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()

这段代码仍然感觉有点老套。我不喜欢声明模块级变量,更不用说使用全局变量了。我欢迎任何避免此类做法并使代码看起来更干净且更可重用的建议。

How can I share a blob of data using a Twisted server, while at the time time periodically updating that data in the background?:

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()

The above code does not work because of the following exception:

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

I would like HTTP clients to access, in this example, http://127.0.0.1:8880/data and retrieve the current value of data, while at the same time have some other task scheduled to update data every so often.

Moreover, I don't really want to use LoopingCall() because I may want to vary the interval depending on whether the update succeeds or not; the update will be some sort of remote API call. Can I use CallLater() in some fashion instead?

I'm sure this is a stupid question! Thanks.

EDIT: thouis helped with properly making the data variable global. For those that follow, here's how to fit callLater() into the code:

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()

This code still feels a bit hacky. I don't like declaring module-level variables, let alone using global variables. I welcome any suggestions that avoid such practises and make the code look cleaner and more re-usable.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

眸中客 2024-11-11 17:27:07

向 update_data() 添加全局定义:

def update_data():
    global data
    data += 1

Add a global def to update_data():

def update_data():
    global data
    data += 1
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文