簡體   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