很多时候,我们最终会在 Python 中编写代码来执行远程请求或读取多个文件或对一些数据做一些事情。在许多这样的情况下,我看到程序员使用一个简单的程序员 for 循环,该循环需要永远完成执行。例如:
import requests
from time import time
url_list = [
"https://via.placeholder.com/400",
"https://via.placeholder.com/410",
"https://via.placeholder.com/420",
"https://via.placeholder.com/430",
"https://via.placeholder.com/440",
"https://via.placeholder.com/450",
"https://via.placeholder.com/460",
"https://via.placeholder.com/470",
"https://via.placeholder.com/480",
"https://via.placeholder.com/490",
"https://via.placeholder.com/500",
"https://via.placeholder.com/510",
"https://via.placeholder.com/520",
"https://via.placeholder.com/530",
]
def download_file(url):
html = requests.get(url, stream=True)
return html.status_code
start = time()
for url in url_list:
print(download_file(url))
print(f'Time taken: {time() - start}')
Output:
<--truncated-->
Time taken: 4.128157138824463
这是一个正常的示例,代码将打开每个 URL,等待它加载,打印其状态代码,然后转到下一个 URL。这种代码非常适合多线程。
现代系统可以运行大量线程,这意味着你可以以非常低的开销一次完成多个任务。为什么我们不尝试使用它来让上面的代码更快地处理这些 URL?
我们将使用 concurrent.futures 库中的 ThreadPoolExecutor。它非常易于使用。让我给你看一些代码,然后解释它是如何工作的。
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed
from time import time
url_list = [
"https://via.placeholder.com/400",
"https://via.placeholder.com/410",
"https://via.placeholder.com/420",
"https://via.placeholder.com/430",
"https://via.placeholder.com/440",
"https://via.placeholder.com/450",
"https://via.placeholder.com/460",
"https://via.placeholder.com/470",
"https://via.placeholder.com/480",
"https://via.placeholder.com/490",
"https://via.placeholder.com/500",
"https://via.placeholder.com/510",
"https://via.placeholder.com/520",
"https://via.placeholder.com/530",
]
def download_file(url):
html = requests.get(url, stream=True)
return html.status_code
start = time()
processes = []
with ThreadPoolExecutor(max_workers=10) as executor:
for url in url_list:
processes.append(executor.submit(download_file, url))
for task in as_completed(processes):
print(task.result())
print(f'Time taken: {time() - start}')
Output:
<--truncated-->
Time taken: 0.4583399295806885
我们的代码快了近 9 倍!我们甚至没有进行任何超级订婚。如果有更多的 URL,性能优势会更高。
所以发生了什么事?当我们调用 executor.submit 时,我们正在向线程池添加一个新任务。我们将该任务存储在进程列表中。稍后我们迭代该过程并打印出结果。
as_completed 方法在完成后立即从进程列表中生成项目(任务)。一个任务可以进入完成状态有两个原因。它已完成执行或已被取消。我们也可以传入一个超时参数as_completed,如果任务耗时超过那个时间段,那么as_completed就会生成任务。
你应该更多地探索多线程。对于琐碎的项目,这是加快代码速度的最快方法。如果想学习,请阅读官方文档https://docs.python.org/3/library/concurrent.futures.html,很有帮助。
本文为原创文章,版权归知行编程网所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ 如何使函数在python中不返回结果09/27
- ♥ 什么是人工智能python11/03
- ♥ Python实战:绘制正弦函数图像09/03
- ♥ Python lambda 的速记用法01/14
- ♥ python中字符串的用途是什么11/13
- ♥ 2020年了,你应该知道怎么用seaborn了!12/31
内容反馈