Jupyter Notebook多进程保存Matplotlib图时外部DataFrame调用报错解决
解决多进程中访问外部DataFrame的问题
为什么会报错?
多进程的每个子进程都有独立的内存空间,主进程中定义的全局变量df不会自动被子进程识别,因此会抛出NameError。
解决方案1:将DataFrame作为参数传递
pool.map默认只能给函数传单个参数,我们可以用pool.starmap传递多参数,或者把参数打包成元组:
import pandas as pd from multiprocess import Pool df = pd.DataFrame({'A':[1,2,3],'B':[1,2,3]}) def do_plot(number, df): import matplotlib.pyplot as plt fig = plt.figure(number) a = df['A'] b = df['B'] plt.scatter(a, b) plt.savefig("%03d.jpg" % (number,)) plt.close() print("Done ", number) if __name__ == '__main__': # 必须添加,避免多进程启动时重复执行代码 pool = Pool(4) # 打包每个任务的参数 tasks = [(num, df) for num in range(4)] pool.starmap(do_plot, tasks)
⚠️ 注意:如果DataFrame体积很大,这种方法会把df复制到每个子进程,占用较多内存。
解决方案2:子进程内部加载DataFrame
如果你的DataFrame是从文件(CSV/Excel等)读取的,可以让每个子进程自行加载,避免主进程复制大对象:
import pandas as pd from multiprocess import Pool def do_plot(number): import matplotlib.pyplot as plt # 子进程内部读取文件生成DataFrame df = pd.read_csv('your_data.csv') # 替换为你的文件路径 fig = plt.figure(number) a = df['A'] b = df['B'] plt.scatter(a, b) plt.savefig("%03d.jpg" % (number,)) plt.close() print("Done ", number) if __name__ == '__main__': pool = Pool(4) pool.map(do_plot, range(4))
这种方法节省内存,但要注意文件读取的IO开销,适合大型数据集场景。
解决方案3:使用共享内存(超大型DataFrame专用)
如果DataFrame极大,不想多次复制,可以通过共享内存传递数据,需先将DataFrame转为可共享的结构,再在子进程中重建:
import pandas as pd import numpy as np from multiprocess import Pool, Manager def init_worker(shared_array, columns): # 在子进程中初始化全局共享DataFrame global df_shared df_shared = pd.DataFrame(shared_array, columns=columns) def do_plot(number): import matplotlib.pyplot as plt fig = plt.figure(number) a = df_shared['A'] b = df_shared['B'] plt.scatter(a, b) plt.savefig("%03d.jpg" % (number,)) plt.close() print("Done ", number) if __name__ == '__main__': df = pd.DataFrame({'A':[1,2,3],'B':[1,2,3]}) df_array = df.values columns = df.columns.tolist() with Manager() as manager: # 创建共享数组 shared_array = manager.list(df_array.tolist()) # 初始化子进程,传递共享数据 pool = Pool(4, initializer=init_worker, initargs=(shared_array, columns)) pool.map(do_plot, range(4))
这种方法内存效率最高,但实现稍复杂,适合超大型数据集场景。
内容的提问来源于stack exchange,提问作者user306204
相关产品推荐
相关产品推荐

