从连续运行的烧瓶应用程序内异步调用函数

时间:2014-01-15 16:35:51

标签: python asynchronous flask celery

我有一个与Dropbox集成的Flask应用程序。我需要通过调用DropboxClient为每个用户创建一个fetch_dropbox_data()个实例。

我似乎无法确定应该如何调用fetch_dropbox_data()

  1. 不阻止用户与网络应用的互动
  2. 仅在每个用户的一个实例中运行
  3. 可以使用或不使用用户交互启动/重新启动
  4. 我应该使用类似Celery的内容吗?或者是否有其他方法可以更好地运作?我开始使用multiprocessing的路径,但它似乎不符合要求。我当然会感谢任何指针。谢谢!

    这是一个简单的例子来说明我正在尝试做的事情:

    from flask import Flask, request, redirect, url_for, session
    app = Flask(__name__)
    
    @app.route('/some/route/')
    def route():
    
        session_access_token = "some_access_token"
    
        # Need to call this asynchronously as to not block
        fetch_dropbox_data(session_access_token)
    
        return "ok"
    
    # Only one DropboxClient instance should be created per user
    def fetch_dropbox_data(session_access_token):
    
    
        client = dropbox.client.DropboxClient(session_access_token)
    
        cursor = None
        while True:
            result = client.delta(cursor)
            cursor = result['cursor']
            if result['reset']:
                print 'RESET'
    
            for dir_path, metadata in result['entries']:
                print "in the for loop"
                if metadata is not None:
                    print '%s was created/updated by' % (dir_path)
    
                else:
                    print '%s was deleted by %s' % (dir_path, session_access_token)
    
            # if has_more is true, call delta again immediately
            if not result['has_more']:
    
                changes = False
                # poll until there are changes
                while not changes:
                    response = requests.get('https://api-notify.dropbox.com/1/longpoll_delta',
                        params={
                            'cursor': cursor,  # latest cursor from delta call
                            'timeout': 120     # default is 30 seconds
                        })
                    data = response.json()
    
                    print "data: %s" % data
    
                    changes = data['changes']
                    if not changes:
                        print 'Timeout, polling again...'
    
                    backoff = data.get('backoff', None)
                    if backoff is not None:
                        print 'Backoff requested. Sleeping for %d seconds...' % backoff
                        time.sleep(backoff)
                    print 'Resuming polling...'
    
        return 'Authenticated.'
    
    
    if __name__ == '__main__':
        app.run(debug=True)
    

1 个答案:

答案 0 :(得分:1)

您可以继续沿着使用多处理的路径执行异步函数调用,如下面的非常基本示例所示。

import multiprocessing

class MetaSingleton(type):
    instance = None
    def __call__(cls, *args, **kw):
        if cls.instance is None:
            cls.instance = super(MetaSingleton, cls).__call__(*args, **kw)
        return cls.instance

class PoolManager(object):
    __metaclass__ = MetaSingleton


    def __init__(self):
        self.pool = None

    def create_pool(self, count=4):
        self.pool = multiprocessing.Pool(processes=count)

    def use_worker(self, func, params, tout=1): 
        result = self.pool.apply_async(func, params)    
        return result.get(timeout=tout)           

    def map_workers(self, func, params):
        return self.pool.map(func, params)

    def get_pool(self):
        return self.pool       

if __name__ == '__main__':


    def test1(x):
        return x*x


    a = PoolManager()
    print id(a)
    a.create_pool()
    print a.get_pool()

    print a.use_worker(test1, [10])



    b = PoolManager()
    print id(b)
    print b.get_pool()

    print b.use_worker(test1, [10])

这需要扩展以跟踪用户执行情况。