Description
Description of the problem
Here is a simple Python script to reproduce the issue.
import pygmt
fig = pygmt.Figure()
fig.basemap(region=[0, 10, 0, 10], projection="X10c/10c", frame="+tFigure1")
print("Openning Figure1")
fig.show(method="external")
When I run the codes in a Python/IPython interpreter, it works well and can open the preview image. However, if I save it in a Python script and run it using python test.py
, sometimes it can open the image but sometimes it fails and gives an error like (I'm using macOS):
The reason is simple, on macOS, we call the open
program to open the image. Because we can't detect the status of the external viewer, the Python script continues to execute the code and exit. When the script exits, Python will call the destructor of the Figure class (i.e., Figure.__del__
method), which deletes the preview directory and also the preview image.
So, the preview image will show if the open
program opens the image before Python deletes it, and will fail to open the image if it's already deleted.
The following script is similar to the above one, but instead, it plots and opens two images.
import pygmt
fig = pygmt.Figure()
fig.basemap(region=[0, 10, 0, 10], projection="X10c/10c", frame="+tFigure1")
print("Openning Figure1")
fig.show(method="external")
fig = pygmt.Figure()
fig.basemap(region=[0, 10, 0, 10], projection="X10c/10c", frame="+tFigure2")
print("Openning Figure2")
fig.show(method="external")
Again, the script works well in a Python/IPython interpreter, but usually can open Figure1 and can't open Figure2 when running a script. Figure1 can be successfully opened because plotting the second figure take some time, so the first Figure.show()
call can open Figure1 before the program exits.
The only solution I can figure out is adding a short pause after calling the external viewer, i.e.,
adding time.sleep(0.5)
at the end of the launch_external_viewer(fname)
function.
Line 195 in 1fb9e2e
It works well for me, and should also work for Linux, but I'm not sure about Windows. The 0.5 second pause time is empirical, and may not work for slow computers.
I opened the PR #1062 with the above solution, so that anyone can test it with/without the pause.