IPython Notebook中subprocess调用脚本的plt.show()图像显示异常
解决IPython Notebook中subprocess启动脚本的Matplotlib图像不显示问题
你遇到的这个问题本质是:用subprocess.Popen启动的外部Python脚本是一个完全独立的进程,它的Matplotlib环境和IPython Notebook的前端没有关联,默认会使用系统的交互式后端(比如TkAgg),所以图像会在终端弹出窗口,而不是嵌入到Notebook里。下面给你几个可行的解决方案,按推荐程度排序:
方案1:直接在Notebook中运行脚本代码(最推荐)
把脚本的逻辑直接整合到Notebook里,或者导入脚本模块,这样Matplotlib会自动使用Notebook的兼容后端。步骤如下:
- 在Notebook的第一个单元格设置Matplotlib后端:
# 静态嵌入图像用这个 %matplotlib inline # 如果需要交互式图像(比如缩放、拖动),用这个 # %matplotlib notebook
- 运行脚本的代码:
你可以把referee.py里的代码直接复制到Notebook的单元格中执行,或者通过添加路径导入模块:
import sys # 添加脚本所在目录到Python路径 sys.path.append("/Jupyter/drone_cat_mouse/referee/") # 导入脚本中的类和函数 from referee import Pose, VisorPainter # 接下来执行你需要的逻辑,比如初始化Pose实例、启动绘图流程等
这样当代码调用plt.show()时,图像就会直接显示在Notebook单元格里了。
方案2:修改子进程脚本,保存图像后在Notebook中显示
如果必须用subprocess启动脚本,那可以让脚本把图像保存为文件,再在Notebook中读取并显示这个文件:
- 修改
referee.py中的绘图结束逻辑:
把原来的plt.show()替换成保存图像的代码(如果脚本是持续更新图像的,可以定期保存):
# 替换plt.show()为以下代码 plt.savefig("/Jupyter/drone_cat_mouse/referee/distance_plot.png") plt.close() # 释放Matplotlib资源,避免内存泄漏
- 在Notebook中启动子进程并显示图像:
import subprocess from IPython.display import Image, clear_output import time # 启动子进程 referee = subprocess.Popen( "/Jupyter/drone_cat_mouse/referee/referee.py /Jupyter/drone_cat_mouse/referee/referee.yml", shell=True ) # 如果脚本是一次性生成图像,等待运行完成后显示 time.sleep(3) # 根据脚本运行时间调整等待时长 clear_output(wait=True) display(Image(filename="/Jupyter/drone_cat_mouse/referee/distance_plot.png")) # 如果脚本是持续更新图像(比如实时绘图),可以循环刷新显示 # try: # while referee.poll() is None: # 子进程仍在运行 # clear_output(wait=True) # display(Image(filename="/Jupyter/drone_cat_mouse/referee/distance_plot.png")) # time.sleep(1) # 每秒刷新一次 # finally: # referee.terminate() # 结束子进程
方案3:配置子进程的Matplotlib后端(不推荐,复杂度高)
理论上可以在子进程脚本开头强制设置Matplotlib为非交互式后端(比如Agg),但这还是需要依赖文件保存或者进程间通信来传递图像数据,操作起来比前两个方案麻烦很多,除非你有特殊需求,否则不建议使用。
内容的提问来源于stack exchange,提问作者Pablo M.
相关产品推荐
相关产品推荐

