这个问题在这里已有答案:
我正在编写一个消耗磁盘空间并且必须不时清理它的服务。在此之前,在请求处理中执行清洁。不幸的是,如果必须清理大磁盘空间,则会耗费大量时间和服务。我试图将清洁程序重写为龙卷风的未来,但却迷失了从发电机制造未来(或类似的东西)的方式。我的代码简化如下:
import tornado
import tornado.ioloop
import tornado.web
from tornado.process import Subprocess
#from tornado.stack_context import run_in_stack_context, NullContext
from time import time
import random
import json
import asyncio
class meta_doc(type):
def __init__(cls, name, bases, methods):
super().__init__(name, bases, methods)
cls.storage_size=0
class Documentation_parsing(tornado.web.RequestHandler, metaclass=meta_doc):
max_storage_size=200
optimal_storage_size=100
cleaning=False
@classmethod
@tornado.gen.coroutine
def _collect_old_folders(cls):
print('start cleaning')
for d in subfolders:
if cls.storage_size<cls.optimal_storage_size:
break
delta=random.randint(5, 15)
time.sleep(random.uniform(0.5, 3))
cls.storage_size-=delta
print('Folder have been deleted. Folder size:', cls.storage_size)
yield None
cls.cleaning=False
print('finish cleaning')
@classmethod
def collect_old_folders(cls):
if not cls.cleaning:
cls.cleaning=True
tornado.ioloop.IOLoop.current().add_future(cls._collect_old_folders, lambda f: f.result())
@tornado.gen.coroutine
def post(self):
request_id=self.get_body_argument("request_id", default='')
self.__class__.storage_size+=random.randint(5, 15)
if self.storage_size>self.max_storage_size:
self.collect_old_folders()
self.write(json.dumps({'request_id': request_id, 'storage_size': self.storage_size}))
print('process request: request_id {0}, storage size {1}'.format(request_id, self.storage_size))
ApplicationSuffixes=[(r'/main_parsing.*', Documentation_parsing)]
if __name__=='__main__':
app = tornado.web.Application(ApplicationSuffixes)
app.listen(9999)
tornado.ioloop.IOLoop.current().start()
此代码返回将来的断言错误。我寻找另一个装饰器,它从发电机或corutine创造未来,但没有找到。请帮我解决这个问题。 UPD。我已经尝试过提到的问题的解决方案,但收到“无法导入run_in_stack_context”。这就是我的代码中注释了这种导入的原因
解决这个问题:
import tornado
import tornado.ioloop
import tornado.web
from tornado.process import Subprocess
#from tornado.stack_context import run_in_stack_context, NullContext
import time
import random
import json
import asyncio
class meta_doc(type):
def __init__(cls, name, bases, methods):
super().__init__(name, bases, methods)
cls.storage_size=0
class Documentation_parsing(tornado.web.RequestHandler, metaclass=meta_doc):
max_storage_size=200
optimal_storage_size=100
cleaning=False
@classmethod
@tornado.gen.coroutine
def _collect_old_folders(cls):
print('start cleaning')
while True:
if cls.storage_size<cls.optimal_storage_size:
break
delta=random.randint(5, 15)
time.sleep(random.uniform(0.5, 3))
cls.storage_size-=delta
print('Folder have been deleted. Folder size:', cls.storage_size)
yield None
cls.cleaning=False
print('finish cleaning')
@classmethod
def collect_old_folders(cls):
def func(inp):
print('called', inp)
if not cls.cleaning:
cls.cleaning=True
future=cls._collect_old_folders()
print(type(future))
tornado.ioloop.IOLoop.current().add_future(future, func)
@tornado.gen.coroutine
def post(self):
request_id=self.get_body_argument("request_id", default='')
self.__class__.storage_size+=random.randint(5, 15)
if self.storage_size>self.max_storage_size:
self.collect_old_folders()
self.write(json.dumps({'request_id': request_id, 'storage_size': self.storage_size}))
print('process request: request_id {0}, storage size {1}'.format(request_id, self.storage_size))
ApplicationSuffixes=[(r'/main_parsing.*', Documentation_parsing)]
if __name__=='__main__':
app = tornado.web.Application(ApplicationSuffixes)
app.listen(8999)
tornado.ioloop.IOLoop.current().start()
评论:装饰者tornado.gen.coroutine返回一个返回未来的函数。所以我只需要调用方法来获得未来。在5.0版本的Tornado中,我可以直接向IOLoop添加未来。唯一的想法是,未来我必须将一个函数作为第二个参数传递。该功能接收例外或未来的表现结果。