0

I have been using this whole script flawlessly on my PC. I attempted to put it on my coworkers PC, but this particular part doesn't seem to work. I am using a tkinter interface to take data from psql and fill a premade fillable PDF using pypdftk, then either saving it using asksaveasfilename and opening it with subprocess.Popen or not saving it and opening it as a temp file using subprocess.run. On my PC both work great. On coworkers PC, neither work.

On my coworkers PC, the save option opens the save dialog with all the correct info as far as I can tell, and lets me go through the process of saving a file as it normally would, but then the file just doesn't save and never actually appears. If I open as a temp file, it throws the exception.

import tkinter as tk
from tkinter import *
from tkinter.ttk import *
import tkinter.messagebox
import pypdftk
from tkinter.filedialog import asksaveasfilename
import os.path
import os
import subprocess
from pathlib import Path

def file_handler(form_path, data, fname):
    try:
        tl2 = tk.Toplevel()
        tl2.wm_title('File Handler')
        w = 340
        h = 55
        ws = tl2.winfo_screenwidth()
        hs = tl2.winfo_screenheight()
        x = (ws/2) - (w/2)
        y = (hs/2) - (h/2)
        tl2.geometry('%dx%d+%d+%d' % (w, h, x, y))
        def save_and_open():
            savefile = asksaveasfilename(defaultextension=".pdf", initialdir="C:\\Desktop", filetypes=[('pdf file', '*.pdf')], initialfile=fname)
            generated_pdf = pypdftk.fill_form(form_path, data, savefile)
            subprocess.Popen(generated_pdf,shell=True)
        def open_without_save():
            try:
                generated_pdf = pypdftk.fill_form(form_path, data)
                os.rename(generated_pdf, generated_pdf+".pdf")
                generated_pdf = generated_pdf+".pdf"
                subprocess.run(generated_pdf,shell=True)
            except:
                tk.messagebox.showerror("Unable to open", "An error has occurred.  Please try again.")
            else:
                tl2.destroy()
            finally:
                if os.path.exists(generated_pdf):
                    os.remove(generated_pdf)
                    print("Successfully removed temp file.")
        save = tk.Button(tl2,text='Save and Open', width=20, command=save_and_open)
        nosave = tk.Button(tl2,text='Open without saving', width=20,command=open_without_save)
        save.grid(row=0, columnspan=2, sticky='NESW', padx=5, pady=10, ipadx=5, ipady=5)
        nosave.grid(row=0, column=2, columnspan=2, sticky='NESW', padx=5, pady=10, ipadx=5, ipady=5)
        tl2.mainloop()
    except:
        tk.messagebox.showerror("Unable to open", "An error has occurred.  Please try again.")

As far as I can tell, everything works until you get into the save_and_open and open_without_save functions. I left in all the libraries I believe are relevant.

I should also mention, I am quite a novice at python. So if any of this is ugly coding, feel free to shame me for it.

update:

I now believe the problem to be here in the pypdftk.py file:

if os.getenv('PDFTK_PATH'):
  PDFTK_PATH = os.getenv('PDFTK_PATH')
else:
  PDFTK_PATH = '/usr/bin/pdftk'
  if not os.path.isfile(PDFTK_PATH):
    PDFTK_PATH = 'pdftk'

My error states pdftk is not a known command. My guess is that there is no environment variable, then it looks to the /usr/bin and cannot find the pdftk file, so it's just making "pdftk" a string? I don't know much about /usr/bin, but is there a way to check that?

NMALM
  • 378
  • 2
  • 19
  • If there are errors shown on the console or terminal, post the full traceback of the error. – acw1668 Mar 24 '21 at 05:06
  • Okay, I've narrowed it to these: "WARNING:root:pdftk test call failed (PDFTK_PATH-'pdftk')." and "'pdftk' is not recognized as an internal or external command, operable program or batch file." – NMALM Mar 24 '21 at 17:09
  • Then you need to install the `pdftk` tool. – acw1668 Mar 24 '21 at 17:34
  • Just realized that. Did that. Uninstalled pypdftk through pip and reinstalled it for good measure, but am still receiving that error. I've read some stuff about setting the path to pdftk.exe but I don't know how or where I would do that. – NMALM Mar 24 '21 at 17:42
  • Okay, I now believe the problem lies in lines 19-24 of pypdftk.py. OP updated – NMALM Mar 24 '21 at 17:55

2 Answers2

1

I was able to fix this problem by going into the pypdftk.py file and changing the paths to raw strings like such:

if os.getenv('PDFTK_PATH'):
  PDFTK_PATH = os.getenv('PDFTK_PATH')
else:
  PDFTK_PATH = r'/usr/bin/pdftk'
  if not os.path.isfile(PDFTK_PATH):
    PDFTK_PATH = r'pdftk'
NMALM
  • 378
  • 2
  • 19
1

What's going on in lines 19-21

if os.getenv('PDFTK_PATH'): is checking to see if the environment variable PDFTK_PATH even exists on your machine. If so, the constant PDFTK_PATH is set to the value provided by the PDFTK_PATH environment key/variable.

Otherwise, it sets PDFTK_PATH to /usr/bin/pdftk. Two things are happening here... First, it provides a path to the binary, i.e., /usr/bin. Second, it provides the name of the binary, i.e., pdftk. In other words, it sets PDFTK_PATH to path + executable filename.

(NOTE: The directory usr/bin is where most executables are stored on machines running Unix-like operating systems, e.g., Mac, Ubuntu, etc. This is alluded to in the repo, see here.)

To err on the side of caution, if not os.path.isfile(PDFTK_PATH): checks to see if the pdftk binary can indeed be found in the /usr/bin/ folder. If not, it sets PDFTK_PATH to pdftk, i.e., it sets the path to the pdftk binary to the very directory in which pypdftk.py is located.

Farther down, the try block runs a test call on whatever the value of PDFTK_PATH was ultimately set to. See lines 46-49. If the binary, pdftk.exe, is not where PDFTK_PATH says it is, then you get the error that you got.

Concerning the r-string

As for casting the string literal to an r-string, that actually did nothing. The r prefix simply redefines the \ as just that, a backslash, rather than allowing the \ to continue to function as cue to an escape sequence. See here and here. You'll notice that neither /usr/bin/pdftk nor pdftk, i.e., where you prepended the r, contain any backslashes.

What I think happened...

After you took the advice of acw1668, and installed the PDF Toolkit (pdftk); and reinstalled the pypdftk package, you had probably fixed the problem. I don't know, but maybe you had not restarted your IDE/editor during these steps? (Side note: Sometimes you need to restart your IDE/editor after changes have been made to your machine's environment variables/settings.)

The short answer: If you're on a windows machine, the install of the pdftk toolkit added PDFTK_PATH to your environment; or, if you're on a Unix-based machine, the install placed the binary in the /usr/bin directory.

Regardless, I assure you the r had nothing to do with it. Now that you know it's working, let's prove it... take out the r, you'll see that it is still working.