I have created a simple data analysis program that takes input from the user of a file name (with.csv extension) and outputs a graph. This has worked fine on my IDE before I used pyinstaller to try make it into an application (I have tried both the basic command pyinstaller my_script_name.py as well as pyinstaller --onefile my_script_name.py)
Now that I have created the applications, I get an "unhandled exception: input(): lost sys.stdin". I assume this is because the program is trying to read a file that is not included in the program/directory. I have also tried adding all .dll files using --add-data but with no luck.
My issue here is that I want the application to take a user input for the file name, read that file into the program, then create the graphic outputs with matplotlib. It seems like everything should work based on other answers I have found (all dependencies appear to be included in the build folder as well). I think the issue lies with taking the user input for the file and I can't figure out how to get around this.
Here is my code:
import pandas as pd
import matplotlib.pyplot as plt
while True:
try:
print("This program analyses data from the T1_Elec and T1_Seb directories only")
print("Please input name of CSV file for analysis (including extension, i.e., file.CSV): ")
file = input()
data_file = pd.read_csv(file)
break
except FileNotFoundError:
print("\nFILE NOT FOUND, please try again")
pass
Active = data_file['Active Power']
time = data_file['Time']
date = data_file['Date'].iloc[2]
fig, ax = plt.subplots(figsize=(8, 7.5), dpi=80)
ax.plot(time, Active)
ax.set(xlabel="Time", ylabel="Active Power", title="Active Power Variation for " + date)
if len(time) > 100:
ax.set_xticks(time[::60])
else:
ax.set_xticks(time[::4])
plt.xticks(rotation=45, ha='right')
plt.grid()
plt.show()
Any help would be greatly appreciated. I have a feeling this could be a simple fix, I just can't think of it or find anything online.
Thanks in advance for your input!
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?
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.
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'
So basically i want to copy the contents of this file to my clipboard
Ive tried many things like using different modules and such but for some reason i just cant do it
import shutil
owl_hub = open('owlhub.txt','r')
if a == "Owl Hub":
lbl.config(text = owl_hub.readlines())
shutil.copy(owlhub.readlines())
Use tkinter; it comes with python and provides a cross-platform way to change the clipboard
import tkinter as tk
root = tk.Tk()
root.withdraw()
root.clipboard_clear()
with open('owlhub.txt') as f:
root.clipboard_append(f.read().strip())
root.update()
root.destroy()
I am working on a script that "reads" PDF files and and then automatically renames the files it recognizes from a dictionary. PyPDF2 however only returns empty lines for some PDFs, while working fine for others. The code for reading the files:
import PyPDF2
# File name
file = 'sample.pdf'
# Open File
with open(file, "rb") as f:
# Read in file
pdfReader = PyPDF2.PdfFileReader(f)
# Check number of pages
number_of_pages = pdfReader.numPages
print(number_of_pages)
# Get first page
pageObj = pdfReader.getPage(0)
# Extract text from page 1
text = pageObj.extractText()
print(text)
It does get the number of pages correctly, so it is able to open the PDF.
If I replace the print(text) by repr(text) for files it doesn't read, I get something like:
"'\\n\\n\\n\\n\\n\\n\\n\\nn\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n'"
Weirdly enough, when I enhance (OCR) the files with Adobe, the script performs slightly worse. It Recognized 140 out of 800 files and after enhancing just 110.
The PDFs are machine readable/searchable, because I am able to copy/paste text to Notepad. I tested some files with "pdfminer" and it does show some text, but also throws in a lot of errors. If possible I like to keep working with PyPDF2.
Specifications of the software I am using:
Windows: 10.0.15063
Python: 3.6.1
PyPDF: 1.26.0
Adobe version: 17.009.20058
Anyone any suggestions? Your help is very much appreciated!
I had the same issue, i fixed it using another python library called slate
Fortunately, i found a fork that works in Python 3.6.5
import slate3k as slate
with open(file.pdf,'rb') as f:
extracted_text = slate.PDF(f)
print(extracted_text)
I have a small program that works fine on my PC but I want to make it portable. What it does is download an image from the internet, set as desktop background, wait one minute and update the image. I know that I cannot write directly to folders like appdata, as I do not know the username of the person using the computer. I need to save the downloaded image somewhere, so I would save it in the windows Temp folder.
Some options I think would be to (However I don't know how to do this in python)
Use something like %temp% to access the folder.
Find out the username of the person running the program and insert into path
Use a variable for the username.
Use relative paths
I would like to try and not have to use another module not by default included in Python 3, as I want to cx_freeze it later on.
import pythoncom
from urllib import request
from win32com.shell import shell, shellcon
from time import sleep
def get_image():
f = open('C:\\Users\\MyUser\\Desktop\\Python\\bg\\bg.jpg', 'wb') #Open old image
f.write(request.urlopen('blalbla.com/foo/img.jpg').read()) #Get new image and write
f.close()
pathtoimg = 'C:\\Users\\MyUser\\Desktop\\Python\\bg\\bg.jpg'
count = 0
while 1:
get_image()
iad = pythoncom.CoCreateInstance(shell.CLSID_ActiveDesktop, None,
pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IActiveDesktop)
iad.SetWallpaper(pathtoimg, 0)
iad.ApplyChanges(shellcon.AD_APPLY_ALL)
count += 1
print(count)
sleep(60)
Use this to locate Temp:
import os
mytmpdir = os.environ['TEMP'] #Must be uppercase