88import tempfile
99import codecs
1010import subprocess
11+ import atexit
12+ import weakref
1113
1214import matplotlib as mpl
1315from matplotlib .backend_bases import RendererBase , GraphicsContextBase ,\
@@ -228,6 +230,7 @@ class LatexManager:
228230 determining the metrics of text elements. The LaTeX environment can be
229231 modified by setting fonts and/or a custem preamble in the rc parameters.
230232 """
233+ _unclean_instances = weakref .WeakSet ()
231234
232235 @staticmethod
233236 def _build_latex_header ():
@@ -244,6 +247,12 @@ def _build_latex_header():
244247 r"\typeout{pgf_backend_query_start}" ]
245248 return "\n " .join (latex_header )
246249
250+ @staticmethod
251+ def _cleanup_remaining_instances ():
252+ unclean_instances = list (LatexManager ._unclean_instances )
253+ for latex_manager in unclean_instances :
254+ latex_manager ._cleanup ()
255+
247256 def _stdin_writeln (self , s ):
248257 self .latex_stdin_utf8 .write (s )
249258 self .latex_stdin_utf8 .write ("\n " )
@@ -265,23 +274,26 @@ def _expect_prompt(self):
265274 return self ._expect ("\n *" )
266275
267276 def __init__ (self ):
277+ # create a tmp directory for running latex, remember to cleanup
278+ self .tmpdir = tempfile .mkdtemp (prefix = "mpl_pgf_lm_" )
279+ LatexManager ._unclean_instances .add (self )
280+
281+ # test the LaTeX setup to ensure a clean startup of the subprocess
268282 self .texcommand = get_texcommand ()
269283 self .latex_header = LatexManager ._build_latex_header ()
270284 latex_end = "\n \\ makeatletter\n \\ @@end\n "
271-
272- # test the LaTeX setup to ensure a clean startup of the subprocess
273285 latex = subprocess .Popen ([self .texcommand , "-halt-on-error" ],
274- stdin = subprocess .PIPE ,
275- stdout = subprocess . PIPE )
286+ stdin = subprocess .PIPE , stdout = subprocess . PIPE ,
287+ cwd = self . tmpdir )
276288 test_input = self .latex_header + latex_end
277289 stdout , stderr = latex .communicate (test_input .encode ("utf-8" ))
278290 if latex .returncode != 0 :
279291 raise LatexError ("LaTeX returned an error, probably missing font or error in preamble:\n %s" % stdout )
280292
281293 # open LaTeX process for real work
282294 latex = subprocess .Popen ([self .texcommand , "-halt-on-error" ],
283- stdin = subprocess .PIPE ,
284- stdout = subprocess . PIPE )
295+ stdin = subprocess .PIPE , stdout = subprocess . PIPE ,
296+ cwd = self . tmpdir )
285297 self .latex = latex
286298 self .latex_stdin_utf8 = codecs .getwriter ("utf8" )(self .latex .stdin )
287299 # write header with 'pgf_backend_query_start' token
@@ -293,19 +305,25 @@ def __init__(self):
293305 # cache for strings already processed
294306 self .str_cache = {}
295307
296- def __del__ (self ):
297- if rcParams . get ( "pgf.debug" , False ):
298- print "deleting LatexManager"
308+ def _cleanup (self ):
309+ if not os . path . isdir ( self . tmpdir ):
310+ return
299311 try :
300312 self .latex_stdin_utf8 .close ()
301313 self .latex .communicate ()
314+ self .latex .wait ()
302315 except :
303316 pass
304317 try :
305- os . remove ( "texput.log" )
306- os . remove ( "texput.aux" )
318+ shutil . rmtree ( self . tmpdir )
319+ LatexManager . _unclean_instances . discard ( self )
307320 except :
308- pass
321+ sys .stderr .write ("error deleting tmp directory %s\n " % self .tmpdir )
322+
323+ def __del__ (self ):
324+ if rcParams .get ("pgf.debug" , False ):
325+ print "deleting LatexManager"
326+ self ._cleanup ()
309327
310328 def get_width_height_descent (self , text , prop ):
311329 """
@@ -723,13 +741,14 @@ def _print_pdf_to_fh(self, fh):
723741 w , h = self .figure .get_figwidth (), self .figure .get_figheight ()
724742
725743 try :
726- # create and switch to temporary directory
727- tmpdir = tempfile .mkdtemp ()
728- cwd = os .getcwd ()
729- os .chdir (tmpdir )
744+ # create temporary directory for compiling the figure
745+ tmpdir = tempfile .mkdtemp (prefix = "mpl_pgf_" )
746+ fname_pgf = os .path .join (tmpdir , "figure.pgf" )
747+ fname_tex = os .path .join (tmpdir , "figure.tex" )
748+ fname_pdf = os .path .join (tmpdir , "figure.pdf" )
730749
731750 # print figure to pgf and compile it with latex
732- self .print_pgf ("figure.pgf" )
751+ self .print_pgf (fname_pgf )
733752
734753 latex_preamble = get_preamble ()
735754 latex_fontspec = get_fontspec ()
@@ -744,26 +763,25 @@ def _print_pdf_to_fh(self, fh):
744763\centering
745764\input{figure.pgf}
746765\end{document}""" % (w , h , latex_preamble , latex_fontspec )
747- with codecs .open ("figure.tex" , "w" , "utf-8" ) as fh_tex :
766+ with codecs .open (fname_tex , "w" , "utf-8" ) as fh_tex :
748767 fh_tex .write (latexcode )
749768
750769 texcommand = get_texcommand ()
751770 cmdargs = [texcommand , "-interaction=nonstopmode" ,
752771 "-halt-on-error" , "figure.tex" ]
753772 try :
754- check_output (cmdargs , stderr = subprocess .STDOUT )
773+ check_output (cmdargs , stderr = subprocess .STDOUT , cwd = tmpdir )
755774 except subprocess .CalledProcessError as e :
756775 raise RuntimeError ("%s was not able to process your file.\n \n Full log:\n %s" % (texcommand , e .output ))
757776
758777 # copy file contents to target
759- with open ("figure.pdf" , "rb" ) as fh_src :
778+ with open (fname_pdf , "rb" ) as fh_src :
760779 shutil .copyfileobj (fh_src , fh )
761780 finally :
762- os .chdir (cwd )
763781 try :
764782 shutil .rmtree (tmpdir )
765783 except :
766- sys .stderr .write ("could not delete tmp directory %s\n " % tmpdir )
784+ sys .stderr .write ("error deleting tmp directory %s\n " % tmpdir )
767785
768786 def print_pdf (self , fname_or_fh , * args , ** kwargs ):
769787 """
@@ -782,22 +800,21 @@ def _print_png_to_fh(self, fh):
782800 converter = make_pdf_to_png_converter ()
783801
784802 try :
785- # create and switch to temporary directory
786- tmpdir = tempfile .mkdtemp ()
787- cwd = os .getcwd ( )
788- os .chdir (tmpdir )
803+ # create temporary directory for pdf creation and png conversion
804+ tmpdir = tempfile .mkdtemp (prefix = "mpl_pgf_" )
805+ fname_pdf = os .path . join ( tmpdir , "figure.pdf" )
806+ fname_png = os .path . join (tmpdir , "figure.png" )
789807 # create pdf and try to convert it to png
790- self .print_pdf ("figure.pdf" )
791- converter ("figure.pdf" , "figure.png" , dpi = self .figure .dpi )
808+ self .print_pdf (fname_pdf )
809+ converter (fname_pdf , fname_png , dpi = self .figure .dpi )
792810 # copy file contents to target
793- with open ("figure.png" , "rb" ) as fh_src :
811+ with open (fname_png , "rb" ) as fh_src :
794812 shutil .copyfileobj (fh_src , fh )
795813 finally :
796- os .chdir (cwd )
797814 try :
798815 shutil .rmtree (tmpdir )
799816 except :
800- sys .stderr .write ("could not delete tmp directory %s\n " % tmpdir )
817+ sys .stderr .write ("error deleting tmp directory %s\n " % tmpdir )
801818
802819 def print_png (self , fname_or_fh , * args , ** kwargs ):
803820 """
@@ -869,3 +886,5 @@ def __init__(self, *args):
869886########################################################################
870887
871888FigureManager = FigureManagerPgf
889+
890+ atexit .register (LatexManager ._cleanup_remaining_instances )
0 commit comments