Search code examples
pythonpython-3.xrelative-pathabsolute-pathos.system

Python utility fails to successfully run a non-Python script that uses relative paths


My Python3 utility has a function that doesn't work (unless it's placed within selected directories, where it can then run the non-python pdflatex scripts successfully). I want to run the utility from a set location on any of the template.tex files I have, stored in various other locations.

The Python utility prompts the user to select a pdflatex template file from an absolute path using a tkinter.filedialog GUI, then runs the user's selected pdflatexscript using, for example: os.system("pdflatex /afullpath/a/b/c/mytemplate.tex")

Python's os.system runs pdflatex, which then runs its mytemplate.tex script. mytemplate.tex has numerous inputs written with relative paths like ./d/another.tex.

So, the Python utility works fine as long as it's in the exact same path as /afullpath/a/b/c/mytemplate.tex that the user selects. Otherwise pdflatex can't finds its own input files. pdflatex delivers an error message like: ! LaTeX Error: File ./d/another.tex not found because the execution path is relative to the Python script and not the pdflatex script.

[pdflatex needs to use relative paths because the folders with its .tex files get moved around, as needed.]

I found the following similar case on Stack Overflow, but I don't think the answers are geared towards this situation: Relative Paths In Python -- Stack Overflow


Solution

  • By referring to other files with relative paths like ./d/another.tex, your mytemplate.tex file is assuming (and requiring) that pdflatex is only run on it from the same directory that mytemplate.tex is located in. You thus need to satisfy this requirement by changing to the directory containing mytemplate.tex before calling os.system:

    input_file = '/afullpath/a/b/c/mytemplate.tex'
    olddir = os.getcwd()
    os.chdir(os.path.dirname(input_file))
    os.system('pdflatex ' + input_file)
    os.chdir(olddir)
    

    Even better is to use subprocess.call, as it handles the change of directory for you and isn't vulnerable to shell quoting issues:

    subprocess.call(['pdflatex', input_file], cwd=os.path.dirname(input_file))