Context
I’ve written a Python code that:
- First generates PlantUML
.uml
files. - Then runs a Java command to locally compile those
.uml
files into.png
diagrams. - Exports those diagrams into a
/images
directory for latex compilation. - Then compiles a latex document that integrates those generated PlantUML diagrams.
Code
The Python that compiles the .uml
files into .png
files is:
def compile_gantt(relative_plant_uml_java_filepath,relative_src_filepath,src_to_gantt_path): os.environ["PLANTUML_LIMIT_SIZE"] = "8192" run_bash_command( f"java -jar {relative_plant_uml_java_filepath} -verbose {relative_src_filepath}{src_to_gantt_path}" ) def run_bash_command(bashCommand): # Verbose call. subprocess.Popen(bashCommand, shell=True) # Silent call. #subprocess.Popen(bashCommand, shell=True, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
And I have written a method that waits until all .png
files are created:
def await_and_verify_compilation_results(self, dir, expected_diagram_filenames,compilation_timout): pause_per_iteration=4 #seconds count=0 # seconds while count<compilation_timout: all_found=True for diagram_filename in expected_diagram_filenames: if not os.path.isfile(f"{dir}/{diagram_filename}"): all_found=False print(f"Did not yet find:{dir}/{diagram_filename}") print(f"Awaiting compilation of Gantt charts: count={count}/{compilation_timout}.") # Break while condition. if all_found: count=compilation_timout+pause_per_iteration # Continue waiting. count=count+pause_per_iteration time.sleep(pause_per_iteration) if not all_found: raise Exception("Did not find all gantt diagrams in time!") time.sleep(30) # allow extra buffer for all images to be finalised.
Issue
The Python code proceeds before the images are completely generated by the Java process.
This means the images are created but it takes a while before they are actually filled with data. Even when they are filled with data it takes a while before they are completed. For example some_diagram.png
may increase in file size from 0 kb, to 800 bytes to 1.2 kb over the timespan of a few seconds. So my “await_and_verify_compilation_results` does not wait until the generation of the pictures is completed.
Question
How can I make the Python code wait until the Java process/PlantUML generation of the .png
files is completed?
Considerations
Since the .png
files are generated automatically, I do not know what their final file size would be. I can set a manual pause of x
seconds after each png
to ensure they are completed on my device, but I would not want others with a faster device to have to wait on my buffer. Additionally such a hardcoded loiter may be unreliable, and inefficient compilation-timewise. So I think the most simple solution would be to modify the python function that calls the Java function. I have not yet found out how to make that wait, nor have I found how I can make the Java function signal that is is completed. (The PlantUML .jar
file is downloaded automatically and I would prefer not to tamper with their file).
Advertisement
Answer
As Gonzalo Odiard already suggested in the comments, the solution could be found by using subprocess.call
instead of subprocess.Popen
. So a solution looked like:
def run_bash_command(bashCommand): # Verbose call. subprocess.call(bashCommand, shell=True) # Silent call. # subprocess.call(bashCommand, shell=True, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
It was verified on Ubuntu 21.04 Using Python 3.6.