Python中多进程编程如何实现?

需求:批量检测 url 有效性

我有一个文本中有 10w 条网址,需要检测所有 url 是否能打开,并将能打开的 url 保存到文本中,不了解 python 的多进程,网上看了一些文章,有些懵逼,求指点

原代码如下:

import requests

url_result_success = [] url_result_failed = []

headers = { ‘Accept’: ‘text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8’, ‘Accept-Encoding’: ‘gzip, deflate, compress’, ‘Accept-Language’: ‘en-us;q=0.5,en;q=0.3’, ‘Cache-Control’: ‘max-age=0’, ‘Connection’: ‘keep-alive’, ‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0’ }

with open(r’urls.txt’, ‘r’) as f: for url in f: url = url.strip() print url try: response = requests.get(url, headers=headers, allow_redirects=True, timeout=5) if response.status_code != 200: raise requests.RequestException(u"Status code error: {}".format(response.status_code)) except requests.RequestException as e: url_result_failed.append(url) continue url_result_success.append(url)

with open(r’valid_urls.txt’, ‘a+’) as f: for url in url_result_success: url = url.strip() f.write(url + ‘\n’)


Python中多进程编程如何实现?

24 回复

IO 密集的不需要多进程,多线程甚至异步都可以


Python多进程编程主要用multiprocessing模块,它绕过了GIL限制,能真正利用多核CPU。核心是Process类,用法和threading类似但更简单。

看个具体例子,计算一个大列表的平方和:

import multiprocessing
import time

def compute_square(numbers, result, index):
    """子进程任务:计算部分数据的平方和"""
    partial_sum = 0
    for num in numbers:
        partial_sum += num * num
    result[index] = partial_sum

def main():
    # 准备测试数据
    data = list(range(1, 1000001))
    
    # 将数据分成4份
    chunk_size = len(data) // 4
    chunks = [
        data[i:i + chunk_size] 
        for i in range(0, len(data), chunk_size)
    ]
    
    # 创建共享内存用于结果收集
    with multiprocessing.Manager() as manager:
        result = manager.list([0] * 4)
        processes = []
        
        # 创建并启动4个进程
        start_time = time.time()
        for i in range(4):
            p = multiprocessing.Process(
                target=compute_square,
                args=(chunks[i], result, i)
            )
            processes.append(p)
            p.start()
        
        # 等待所有进程完成
        for p in processes:
            p.join()
        
        total_sum = sum(result)
        elapsed = time.time() - start_time
    
    print(f"多进程计算结果: {total_sum}")
    print(f"耗时: {elapsed:.2f}秒")
    
    # 对比单进程版本
    start_time = time.time()
    single_result = sum(x*x for x in data)
    single_elapsed = time.time() - start_time
    
    print(f"\n单进程计算结果: {single_result}")
    print(f"耗时: {single_elapsed:.2f}秒")
    print(f"加速比: {single_elapsed/elapsed:.1f}倍")

if __name__ == "__main__":
    main()

关键点说明:

  1. Process类创建进程,target指定要执行的函数,args传参数
  2. start()启动进程,join()等待进程结束
  3. Manager()管理进程间通信,这里用了共享列表
  4. 数据分片处理是常见模式,避免进程间竞争
  5. if __name__ == "__main__"在Windows下必须写,防止子进程重复执行

更现代的写法可以用Pool

from multiprocessing import Pool

def square(x):
    return x * x

with Pool(4) as pool:
    results = pool.map(square, range(1000))

进程池适合任务均匀的场景,自动管理进程创建和任务分配。

多进程适合CPU密集型任务,进程间通信用Queue、Pipe或共享内存。

request 会阻塞 上 aiohttp 吧

gevent 略重,async 了解下,python3.6+ 自带

golang 了解下

asyncio + aiohttp 了解下。

开一百个线程就行,10w 没多久

这并不是 cpu 密集的程序考虑 线程 或者 异步

可以使用 head 代替 get,用多线程就可以,时间看带宽

多线程即可,多进程会受限于你 CPU 的数目。

代码要在 2003 上跑,没法装 3.6.。。
嗯,用多线程
找到过相关文章,值得研究
你说的知道,但没有深入看
下午小区周边光纤让修地铁的干断了,才来的网。。。。

生产者 消费者模式的多线程就行,
用 queue 队列存取数据
生产者往 queue 里面存数据,
消费者里面用一个 while True 死循环 从 queue 里面取数据.
设置一个终止的毒丸.

要恶补基础知识了。。


类似这样, 把读文件替换到 生产者里面,
requests 验证放到消费者里面

有推荐的书看么,程序设计模式之类的

多线程不需要书啊, 最基本的生产者 消费者模式,
java python 都是一样的.

好的,我好好看看你的代码,感谢!~

我想了解下这两个 join 函数的意义是什么呢。萌新一时没看懂

Python 里用多进程多线程直接上 concurrent future,基本上不用关心啥细节

Aiohttp 了解下。。。

grequests 了解下

golang 了解下

足够方便

回到顶部