Как я могу поделиться блоком данных с помощью сервера 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()
Этот код все еще кажется немного хакерским. Мне не нравится объявлять переменные уровня модуля, не говоря уже об использовании глобальных переменных. Я приветствую любые предложения, которые избегают такой практики и делают код более чистым и пригодным для повторного использования.
data
атрибутомDataPage
. Или атрибут какого-то другого объекта, к которомуDataPage
имеет доступ. - person Jean-Paul Calderone   schedule 04.05.2011