如何在龙卷风中启动后台任务,这不会阻止请求处理? [重复]

问题描述 投票:1回答:1

这个问题在这里已有答案:

我正在编写一个消耗磁盘空间并且必须不时清理它的服务。在此之前,在请求处理中执行清洁。不幸的是,如果必须清理大磁盘空间,则会耗费大量时间和服务。我试图将清洁程序重写为龙卷风的未来,但却迷失了从发电机制造未来(或类似的东西)的方式。我的代码简化如下:

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”。这就是我的代码中注释了这种导入的原因

python-3.x tornado nonblocking
1个回答
0
投票

解决这个问题:

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添加未来。唯一的想法是,未来我必须将一个函数作为第二个参数传递。该功能接收例外或未来的表现结果。

© www.soinside.com 2019 - 2024. All rights reserved.