当前位置: 首页 > 科技观察

Python多线程和多处理初学者指南

时间:2023-03-18 01:24:36 科技观察

如果使用正确的数据结构和算法,使用Python分析数据有时可以显着提高程序的速度。实现这一点的一种方法是使用多线程(multithreading)或多处理(multiprocessing)。在本文中,我们不会详细讨论多线程或多处理的内部结构。相反,让我们举个例子,编写一个小的Python脚本来从Unsplash下载图像。我们将从一次下载一个图像的版本开始。接下来,我们使用线程来提高执行速度。多线程简单地说,线程允许您并行运行程序。花费大量时间等待外部事件的任务通常很适合线程化。它们也称为I/O绑定任务,例如从文件读取和写入、网络操作或使用API进行在线下载。让我们看一个显示使用线程的好处的示例。1.无线程在这个例子中,我们想通过顺序运行程序,看看从UnsplashAPI下载15张图片需要多长时间:importrequestsimporttimeimg_urls=['https://images.unsplash.com/photo-1516117172878-fd2c41f4a759','https://images.unsplash.com/photo-1532009324734-20a7a5813719','https://images.unsplash.com/photo-1524429656589-6633a470097c','https://images.unsplash.com/photo-1530224264768-7ff8c1789d79','https://images.unsplash.com/photo-1564135624576-c5c88640f235','https://images.unsplash.com/photo-1541698444083-023c97d3f4b6','https://images.unsplash.com/photo-1522364723953-452d3431c267','https://images.unsplash.com/photo-1513938709626-033611b8cc03','https://images.unsplash.com/photo-1507143550189-fed454f93097's,'https://images.unsplash.com/photo-1493976040374-85c8e12f0c0e','https://images.unsplash.com/photo-1504198453319-5ce911bafcde','https://images.unsplash.com/photo-1530122037265-a5f1f91d3b9://images.unsplash.com/photo-1516972810927-80185027ca84','https://images.unsplash.com/photo-1550439062-609e1531270e','https://images.unsplash.com/photo-1549692520-acc6669e2f0c']start=time.perf_counter()#starttimerforimg_urlinimg_urls:img_name=img_url.split('/')[3]#getimagenamefromurlimg_bytes=requests.get(img_url).contentwithopen(img_name,'wb')asimg_file:img_file.write(img_bytes)#saveimagetodiskfinish=time.perf_counter()#endtimerprint(f"Finishedin{round(finish-start,2)}seconds")#resultsFinishedin23。101926751秒一共用时23秒2.多线程让我们看看Python中的threading模块如何显着提高我们的程序执行:importtimefromconcurrent.futuresimportThreadPoolExecutordefdownload_images(url):img_name=img_url.split('/')[3]img_bytes=requests.get(img_url).contentwithopen(img_name),'wb')asimg_file:img_file.write(img_bytes)print(f"{img_name}wasdownloaded")start=time.perf_counter()#starttimerwithThreadPoolExecutor()asexecutor:results=executor.map(download_images,img_urls)#thisisSimilartomap(func,*iterables)finish=time.perf_counter()#endtimerprint(f"Finishedin{round(finish-start,2)}seconds")#resultsFinishedin5.544147536seconds我们可以看到,与没有线程的代码相比,使用线程代码可以提供显着加速。从23秒到5秒。对于此示例,请注意创建线程会产生开销,因此将线程用于多个API调用而不只是单个调用是有意义的。此外,对于数据处理等密集计算,图像处理多处理比线程处理性能更好。