繁体   English   中英

在python龙卷风上并行运行功能

[英]run function parallel on python tornado

我目前正在tornado框架上使用python3 (仍是初学者)进行开发,并且我想在后台运行一个函数。 更准确地说,该功能的任务是下载一个大文件(逐块),并在每个块下载后可能还要执行更多操作。 但是调用函数不应等待下载函数完成,而应继续执行。

下面是一些代码示例:

@gen.coroutine
def dosomethingfunc(self, env):
    print("Do something")

    self.downloadfunc(file_url, target_path) #I don't want to wait here

    print("Do something else")


@gen.coroutine
def downloadfunc(self, file_url, target_path):

    response = urllib.request.urlopen(file_url)
    CHUNK = 16 * 1024

    with open(target_path, 'wb') as f:
        while True:
            chunk = response.read(CHUNK)
            if not chunk:
                break
            f.write(chunk)
            time.sleep(0.1) #do something after a chunk is downloaded - sleep only as example

我已经在stackoverflow https://stackoverflow.com/a/25083098/2492068上阅读了此答案,并尝试使用它。

其实我想,如果我用@gen.coroutine但没有yielddosomethingfunc将继续无需等待downloadfunc完成。 但是实际上行为是相同的(无论是否产生收益)-仅在downloadfunc完成下载后才打印"Do something else ”。

我在这里想念的是什么?

为了使Tornado的异步功能受益,必须在某个时刻yielded非阻塞函数。 由于downloadfunc的代码全部被阻塞,因此dosomethingfunc在调用的函数完成之前不会获得控制权。

您的代码有几个问题:

所以downloadfunc看起来像:

@gen.coroutine
def downloadfunc(self, file_url, target_path):

    client = tornado.httpclient.AsyncHTTPClient()

    # below code will start downloading and
    # give back control to the ioloop while waiting for data
    res = yield client.fetch(file_url)

    with open(target_path, 'wb') as f:
        f.write(res)
        yield tornado.gen.sleep(0.1)

要通过流(按块)支持来实现它,您可能需要这样做:

# for large files you must increase max_body_size
# because deault body limit in Tornado is set to 100MB

tornado.web.AsyncHTTPClient.configure(None, max_body_size=2*1024**3)

@gen.coroutine
def downloadfunc(self, file_url, target_path):

    client = tornado.httpclient.AsyncHTTPClient()

    # the streaming_callback will be called with received portion of data
    yield client.fetch(file_url, streaming_callback=write_chunk)

def write_chunk(chunk):
    # note the "a" mode, to append to the file
    with open(target_path, 'ab') as f:
        print('chunk %s' % len(chunk))
        f.write(chunk)

现在,您可以在dosomethingfunc调用它而不使用yield ,其余功能将继续进行。

编辑

服务器和客户端均不支持(公开)修改块大小。 您也可以查看https://groups.google.com/forum/#!topic/python-tornado/K8zerl1JB5o

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM