Python中进程池的使用问题与解决方案
#使用进程池将一个目录复制到其他目录下
def myCopy(file):
# 文件与旧路径拼接为绝对路径
newSrcpath = os.path.join(src, file)
# 文件与旧路径拼接为绝对路径
newDispath = os.path.join(dst, file)
open(newDispath, ‘wb’).write(open(newSrcpath, ‘rb’).read())
print(‘文件写入完成’)
src = r’C:\Users\様\Desktop\md 集合’
dst = r’D:\Class 资料\多线程测试’
if name == ‘main’:
start = time.time()
#读取文件以列表形式返回
fileList = os.listdir(src)
#创建线程池
pp = Pool()
#开启线程池
pp.map(myCopy,fileList)
pp.close()
pp.join()
end = time.time()
print(‘用时’, end - start, ‘秒’)
print(‘OVER’)
我想用进程池实现一个将一个目录下的所有文件复制到另一个目录的文件下,还是用多进程改的,结果报了许多语法错误~求 dalao 帮忙看一下~~~给点意见
Python中进程池的使用问题与解决方案
在Python里用进程池,multiprocessing.Pool 确实是个好东西,但有几个坑得注意。
1. 全局变量和初始化问题
子进程不继承父进程的全局变量状态。如果你需要在每个子进程里做初始化(比如开数据库连接),用 initializer 和 initargs:
from multiprocessing import Pool
import sqlite3
def init_worker(db_path):
global conn
conn = sqlite3.connect(db_path) # 每个子进程独立的连接
def query_worker(query):
# 直接使用初始化好的conn
return conn.execute(query).fetchall()
if __name__ == '__main__':
with Pool(processes=4, initializer=init_worker, initargs=('my.db',)) as pool:
results = pool.map(query_worker, ['SELECT * FROM table1', 'SELECT * FROM table2'])
2. Windows下的无限递归
在Windows上,由于没有fork,模块会被重复导入。必须把进程池的创建放在 if __name__ == '__main__': 保护下,否则会递归创建子进程直到崩溃。
3. 任务结果太大撑爆内存
map 会等所有任务完成,一次性返回全部结果列表。如果结果集很大,用 imap 或 imap_unordered 来迭代获取,避免内存爆炸:
with Pool(4) as pool:
for result in pool.imap(worker_func, large_task_list, chunksize=10): # chunksize调优
# 处理每个结果
process(result)
4. 任务异常静默失败
默认情况下,子进程中的异常不会直接抛出到主进程。可以用 apply_async 配合 get() 来捕获:
with Pool(4) as pool:
async_result = pool.apply_async(func_with_error, args=(1, 2))
try:
result = async_result.get(timeout=5)
except Exception as e:
print(f"任务失败: {e}")
5. 僵尸进程和资源释放
一定要用 with 语句或者显式调用 pool.close() 和 pool.join()。否则子进程可能变成僵尸进程。
6. 共享数据开销大
进程间通信(IPC)开销大。如果只是读共享数据,用 multiprocessing.Manager 或 shared_memory(Python 3.8+);如果数据量大且只读,考虑用全局变量配合初始化。
7. 调试困难
子进程的 print 和日志可能不显示。可以配置日志模块,或者用 multiprocessing.log_to_stderr()。
总结:用进程池注意初始化、内存、异常和资源清理。

