【问题标题】:Python Multiprocessing all Functions within an ArrayPython 多处理数组中的所有函数
【发布时间】:2021-09-10 03:40:08
【问题描述】:

我想在 Python 中有一个函数数组。 像这样:

def download(x,y):
      r = requests.get(x, allow_redirects=True)
      open(y, 'wb').write(r.content)

array = [download(url,filename),download(url2,filename2)]

现在我想使用多处理或多线程(取决于哪个更好)同时运行所有这些。

但是函数的数量可能会增加,所以我正在努力运行多线程。

有什么建议吗?

【问题讨论】:

    标签: python multithreading multiprocessing python-multiprocessing python-multithreading


    【解决方案1】:

    使用多处理,类似这样。

    • 这是使用进程池;对于网络 IO 绑定操作,您可以改用 multiprocessing.pool.ThreadPool() 来运行单个进程。
    • 默认情况下,Pool() 为您拥有的每个 CPU 生成一个工作器。您可能希望向上或向下调整。
    • 使用requests 会话比直接使用requests.get() 更有效(TCP、HTTP、TLS 开销)。
    • 你错过了resp.raise_for_status();这意味着您最终可能会保存 404 或 500 响应,就好像一切正​​常。 (您现在可能希望添加一些异常处理;任何失败的作业都会向上传播以关闭池并终止其他作业。)
    • 使用stream=Trueresp.iter_content() 将避免将内容缓冲到内存中。
    • imap_unordered() 是高级池操作中最快的,但顾名思义,它失去了作业的顺序。在这种情况下应该没关系。
    • 如果你有更多的工作,你可以使用chunksize参数优化一些池开销,这基本上意味着单个工作人员将被发送多个工作项。
    import multiprocessing
    import requests
    
    sess = requests.Session()
    
    
    def download(job):
        url, filename = job
        resp = sess.get(url, allow_redirects=True, stream=True)
        resp.raise_for_status()
        with open(filename, "wb") as f:
            for chunk in resp.iter_content(524288):
                f.write(chunk)
    
    
    def main():
    
        jobs = [
            (url, filename),
            (url2, filename2),
        ]
    
        with multiprocessing.Pool() as p:
            for _ in p.imap_unordered(download, jobs):
                pass
    
    
    if __name__ == "__main__":
        main()
    

    【讨论】:

    • 它给了我以下错误信息:“ModuleNotFoundError: No module named 'requests'”,虽然我 100% 确定已安装 - 我经常使用它
    • 该错误消息与此代码完全无关,特别是如果您可以使用 requests 否则。您的 Python 安装/virtualenvs/... 可能有些问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-31
    • 2014-03-24
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2017-05-27
    相关资源
    最近更新 更多