“用代码下载10张图片,一张下完才开始下下一张,太慢了?”
“写的监控程序,既要采集数据又要显示结果,只能二选一?”
——之前写的代码都是“单线作战”,同一时间只干一件事。今天咱们学进程和线程,这两个“并行处理神器”能让代码同时执行多个任务,下载文件、监控系统、爬虫采集都能效率翻倍,这才是Python高手的干活方式。
一、先搞懂:进程和线程是什么?
用生活场景类比最容易理解:进程是“一个独立的工厂”,有自己的厂房和设备(系统资源);线程是“工厂里的工人”,共享厂房资源,同时干不同的活。比如打开微信(一个进程),里面的聊天、朋友圈、支付就是不同的线程。
核心关系:一个进程可以包含多个线程,线程共享进程的资源,切换速度比进程快;进程之间相互独立,资源不共享,稳定性更高。
二、多进程:让代码“开多个工厂”
多进程就是同时启动多个独立程序(工厂),适合CPU密集型任务(比如大量计算)。Python用multiprocessing模块实现多进程,跨平台兼容性好。
from multiprocessing import Processimport timedef calculate_square_sum(num_range): start = time.time() total = sum(x*x for x in num_range) end = time.time() print(f"计算结果:{total},耗时:{end-start:.2f}秒")if __name__ == "__main__": ranges = [range(1, 10000000), range(10000000, 20000000), range(20000000, 30000000)] print("单进程执行:") start_single = time.time() for r in ranges: calculate_square_sum(r) print(f"单进程总耗时:{time.time()-start_single:.2f}秒\n") print("多进程执行:") start_multi = time.time() processes = [] for r in ranges: p = Process(target=calculate_square_sum, args=(r,)) processes.append(p) p.start() for p in processes: p.join() print(f"多进程总耗时:{time.time()-start_multi:.2f}秒")
运行后会发现,多进程总耗时不到单进程的1/3,效率提升明显。避坑点:Windows系统中,多进程代码必须放在if __name__ == "__main__"下,否则会报错。
三、多线程:让代码“多工人干活”
多线程是在一个进程里启动多个线程,适合IO密集型任务(比如下载文件、网络请求)。Python用threading模块实现多线程,比多进程更轻量。
import threadingimport requestsimport timedef download_image
(url, filename): start = time.time() response = requests.get(url) with open(f"images/{filename}", "wb") as f: f.write(response.content) end = time.time() print(f"《{filename}》下载完成,耗时:{end-start:.2f}秒")if __name__ == "__main__": import os os.makedirs("images", exist_ok=True) image_urls = [ ("https://xxx.com/img1.jpg", "风景1.jpg"), ("https://xxx.com/img2.jpg", "风景2.jpg"), ("https://xxx.com/img3.jpg", "风景3.jpg") ] print("多线程下载开始:") start = time.time() threads = [] for url, name in image_urls: t = threading.Thread(target=download_image, args=(url, name)) threads.append(t) t.start() for t in threads: t.join() print(f"全部下载完成,总耗时:{time.time()-start:.2f}秒")
如果用单线程下载,总耗时是3个文件耗时之和;多线程则是“同时下载”,总耗时接近最慢的那一个文件,效率提升非常直观。
四、ThreadLocal:线程的“专属记事本”
线程共享进程资源,但有时候每个线程需要自己的“私有数据”(比如爬虫线程的cookie、用户线程的登录信息),用ThreadLocal就能给每个线程分配独立的存储空间,不用手动传递参数,代码更简洁。
import threadinglocal_data = threading.local()def worker(worker_id): local_data.worker_id = worker_id print_task()def print_task(): print(f"线程{threading.current_thread().name}:工人编号{local_data.worker_id},开始工作")if __name__ == "__main__": threads = [] for i in range(3): t = threading.Thread(target=worker, args=(i+1,), name=f"WorkerThread-{i+1}") threads.append(t) t.start() for t in threads: t.join()
运行后会看到,每个线程都能正确获取自己的worker_id,互不干扰。ThreadLocal常用来处理Web开发中的用户会话、爬虫中的线程私有配置等场景。
五、进程 vs 线程:该选哪个?一张表说清
新手最纠结“什么时候用进程,什么时候用线程”,这张对比表直接抄作业:
对比维度 | 多进程 | 多线程 |
|---|
核心优势 | 稳定性高,适合CPU密集型任务 |
轻量快速,适合IO密集型任务 |
资源占用 | 高(独立资源) | 低(共享资源) |
切换速度 | 慢 | 快 |
适用场景 | 大量计算(如数据分析) | 下载、爬虫、网络请求 |
记住一个简单原则:计算多就用多进程,等待多就用多线程。
六、分布式进程:让多台电脑“一起干活”
如果一个任务太庞大,单台电脑的多进程/多线程也不够用,就需要“分布式进程”——让多台电脑同时执行任务,比如用10台电脑一起爬取一个大型网站的数据。Python用multiprocessing的managers模块实现分布式进程,核心是“主进程管理任务,子进程执行任务”。
from multiprocessing.managers import BaseManagerimport queuetask_queue = queue.Queue()result_queue = queue.Queue()class QueueManager(BaseManager): passQueueManager.register('get_task_queue', callable=lambda: task_queue)QueueManager.register('get_result_queue', callable=lambda: result_queue)manager = QueueManager(address=('', 5000), authkey=b'python30')manager.start()task = manager.get_task_queue()result = manager.get_result_queue()for i in [10, 20, 30]: print(f"发送任务:计算{i}的平方") task.put(i)for _ in range(3): r = result.get(timeout=10) print(f"接收结果:{r}")manager.shutdown()from multiprocessing.managers import BaseManagerclass QueueManager(BaseManager): passQueueManager.register('get_task_queue')QueueManager.register('get_result_queue')server_addr = '192.168.1.100' manager = QueueManager(address=(server_addr, 5000), authkey=b'python30')manager.connect()task = manager.get_task_queue()result = manager.get_result_queue()while True: try: n = task.get(timeout=1) print(f"执行任务:计算{n}的平方") result.put(f"{n}的平方是{n*n}") except queue.Empty: print("任务执行完毕") break
把子进程代码放到多台电脑上运行,就能实现分布式计算,任务执行效率随电脑数量倍增。
今天的内容核心是“并行处理”:多进程和多线程解决单台电脑的效率问题,分布式进程解决多台电脑的协同问题。新手不用急于掌握分布式进程,先把多线程(处理IO任务)和多进程(处理计算任务)的基础用法练熟,日常开发就足够用了。记住,用对并行方式,代码效率能提升10倍甚至100倍。
【今日任务】用多线程实现“同时下载2张图片+播放提示音”的功能:① 下载图片用requests模块;② 播放提示音用winsound模块(Windows)或playsound模块(Mac);③ 确保下载和播放同时进行。
以上就是今天给你分享的内容,觉得有用的话欢迎点赞收藏哦!
如果你也对Python这门编程感兴趣的话,欢迎加入我们。(小白也可以参加)
三更老师亲自上课示范,2天:理论+实操教学+直播教学演示+课后辅导获取方式:
1.关注下方公众号↓↓↓↓
2.点赞+再看
3.在后台发送:“python” 即可领取资料福利/开通上课权限
资料已经打包好了,需要的关注公众号发送“111”领取