我倾向于在 Jupyter Notebook 和 Wing IDE 之间来回切换来调试代码。我喜欢 Jupyter 笔记本的一点是,我可以运行一个单元并生成一系列图像,代码如下:
import matplotlib.pyplot as plt
for i in range(10):
...do stuff...
plt.plot(image)
plt.show()
所有图像都在 jupyter 单元输出区域中一个接一个地完美结束,并且可以通过滚动该区域轻松查看。
虽然我经常想进入调试器编写新代码或调试某些内容,但我还没有找到一个好的机制来执行类似的操作。
有什么建议吗?
一种选择是编写一个函数,将所有图像写入磁盘,然后仅使用照片查看应用程序查看这些图像,但我想知道是否还有另一种方法。
可能要做的事情是使用 wingdbstub,这样您就可以在 Jupyter 上下文中进行调试。 http://wingware.com/doc/howtos/jupyter对此进行了详细描述 - 限制是您无法调试 .ipynb 文件中的代码,但您可以将大多数内容放入 .py 文件中。
截至 2024 年,您完全可以在 VS Code 中执行此操作。 在带有 python 扩展的 VS Code 中打开笔记本。
然后运行所有单元格,直到您要调试的单元格。
在要调试的单元格中设置断点。
选择
Debug cell
选项,VS Code 将进入调试模式。它将停在您的断点处,您可以单步执行它,还可以输入驻留在其他单元格中的代码。
这是 VS Code 之前的答案...
我想出了一种效果很好的方法:
使用非交互式后端来避免图像弹出
将所有对 plt.show() 的调用替换为自己的函数 my_plt_show(),其中:
<html> <img src="img_0000.jpg" /> <br /> <img src="img_0001.jpg" /> <br /> <img src="img_0002.jpg" /> <br /> <img src="img_0003.jpg" /> <br />
运行后或调试时,只需在浏览器中保持 all.html 文件打开,它的行为几乎就像 jupyter 单元的输出一样。
这是我的示例代码:
I_AM_IN_JUPYTER = False
SCRATCH_IMAGE_DIR = 'C:\\Work\\ScratchImages'
SCRATCH_IMAGE_NUM = 0
if I_AM_IN_JUPYTER:
get_ipython().magic('matplotlib inline')
else:
# use non-interactive back-end to avoid images from popping up
# See: http://stackoverflow.com/questions/9622163/save-plot-to-image-file-instead-of-displaying-it-using-matplotlib-so-it-can-be
from matplotlib import use
use('Agg')
# function to show a plot or write it to disk
def my_plt_show():
global I_AM_IN_JUPYTER, SCRATCH_IMAGE_NUM, f_html
plt.show()
if I_AM_IN_JUPYTER == False:
# at start
if SCRATCH_IMAGE_NUM == 0:
# clean out the scratch image dir
files = glob.glob(SCRATCH_IMAGE_DIR+'\\*')
for f in files:
os.remove(f)
# open 'all.html' that displays all the images written
f_html = open(SCRATCH_IMAGE_DIR+'\\all.html', 'w')
f_html.write('<html>\n')
# save all images to a scratch dir
fname = 'img_{:04d}.jpg'.format(SCRATCH_IMAGE_NUM)
plt.savefig(SCRATCH_IMAGE_DIR+'\\'+fname)
fig = plt.gcf() # get reference to the current figure
plt.close(fig) # and close it
f_html.write('<img src="'+fname+'" /> <br />\n')
f_html.flush() # flush it directly to disk, for debug purposes.
SCRATCH_IMAGE_NUM += 1