Converting Image Converter python program to Exe not executing properly - python

i am trying to convert my ImageConverter.py program to an Executable. I use
python3.6.7
pyinstaller --onefile ImageConverter.py
The Executable is made along with the folder pycache , build, and dist
The executable file is in the dist folder, when I try to run the exe the terminal pops up and performs the program and says complete. However no jpeg files are created or in the dist folder. I have also made sure my original .py file, along with my png files are also in the dist folder with the exe. is there something im missing here? are the converted jpeg files in another location?
The ImageConverter.py program uses PIL python package, it open the png files, converts them to RGB, than saves them as jpegs. The program works when running it as usual in terminal using python3 but does not work when trying the exe. any help is appreciated! thanks
ImageConverter.py. :
from PIL import Image #Python Image Library - Image Processing
import glob
import os
import sys
application_path = os.path.dirname(sys.executable)
print(glob.glob("*.png"))
#Iterate through all the images
#Convert images to RGB
#Save Images
for files in glob.glob("*.png"):
im = Image.open(files)
rgb_im = im.convert("RGB")
rgb_im.save(files.replace("png", "jpeg"), quality=95)
output_path = os.path.join(application_path, f'images')
Ive tried to run the executable multiple times. I put the png files and also .py into the dist folder where the exe exists and run. I was expecting the png files to convert to jpeg files, leaving png and jpegs in the dist folder after running exe. However terminal said :
PythonPractice/ImageProcessingPractice/dist/ImageConverter ; exit;
[]
logout
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.
[Process completed]
There is no converted Jpegs in the dist folder

sys.executable is the location of the Python interpreter you are running, e.g. /usr/bin/python3 or C:\Program Files\Python\Scripts\python.exe, not the location of the script you are running.
Therefore, for a system-installed Python binary, os.path.dirname(sys.executable) will return something like /usr/bin or C:\Program Files\Python\Scripts, and os.path.join(application_path, f'images') will return something like /usr/bin/images or C:\Program Files\Python\Scripts\images.
But for a PyInstaller program that used --onefile, that's likely a temporary directory somewhere that gets cleaned up right after the program is finished running.
It might make more sense to just use
output_path = 'images'
without any prefix, which should be relative to the current working directory (wherever you are when you run the script).

Related

Unable to include .txt files when converting a .py to .exe

I have recently made an app that does automatic assigment submissions using selenium. I would like to convert this .py file to a .exe so i can give it to others to use on thier computers.
This is the current directory of the project:
C:
canvas automation
chromedriver.exe
main.py
canvas_subjects.txt
In the main.py file, it uses canvas_subjects.txt file as below:
with open('c:/canvas automation/canvas_subjects.txt', 'r+') as subjects:
chrome_dir = 'C:/PythonProjects/Web Scraping/Selenium/chromedriver.exe'
driver = webdriver.Chrome(chrome_dir)
driver.minimize_window()
if subjects.read() != '':
# does the rest of the program here
When i try and convert main.py to .exe, running the .exe file produces the error:
Failed to execute main script
I'm guessing that when it runs the python script, it cannont find the following directory:
c:/canvas automation/canvas_subjects.txt
To convert this file to .exe, i have tried using pyinstaller:
C:\Users\user> pip install pyinstaller
C:\Canvas Automation> pyinstaller main.py
# also tried
C:\Canvas Automation> pyinstaller --onefile -w main.py
.exe file is created but outputs the same error.
I have tried auto-py-to-exe but it says that you need to incorporate the following code into your script so that the .exe file can find the directory but i do not understand how to use it:
def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
You can't include a txt file in an exe like that. You have 2 solutions here:
Deliver your .txt file alongside the .exe like a part of the installation
Put the content of your text file inside a .py file as a string variable.
NB1: Are you sure you need an exe? could you not distribute it as a python soft, needing python to be executed?
NB2: Either way, you really should not use absolute paths like 'c:...' if you plan to distribute your soft
If you are having trouble including .txt files, try the following command to enable it in order:
CTRL+A
Backspace
CTRL+S
ALT+F4
If problems persist, please let me know.

How to specify pyinstaller resource files correctlly?

I want to make a runnable .py application by double click in Linux.
First, I tried a simple example:
#!/usr/bin/env python3
import cv2
img= cv2.imread('/home/andrei/WTZ/code/Computer-Vision-with-Python/DATA/test_image.jpg')
cv2.imshow('It works?', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
It just opens an image, nothing special.
I installed pyinstaller and I ran the following command in the terminal:
pyinstaller --onefile --add-data="/home/andrei/WTZ/code/Computer-Vision-with-Python/DATA/test.jpg;/home/andrei/WTZ/code/Computer-Vision-with-Python/DATA/test.jpg" test.py
And I encounter the following error:
pyinstaller: error: argument --add-data: invalid add_data_or_binary value: '/home/andrei/WTZ/code/Computer-Vision-with-Python/DATA/test.jpg;/home/andrei/WTZ/code/Computer-Vision-with-Python/DATA/test.jpg'
What am I doing wrong?
Ran this on my machine
pyinstaller --add-binary C:\Users\jezequiel\Desktop\diagram_new.png;.\images d.py
and the .PNG file was copied to a subdirectory named images in the folder containing the d.exe file.
So recommended approach is the first make a main.spec file -
pyi-makespec --windowed main.py
you should then get a main.spec file that you can call pyinstaller with - so you don't need to pass in all resource files via command line.
Then, in your main.spec file (which is actually python code), you should have something like
a = Analysis(
...
)
Assuming your resources are in a resources directory in the root of your project, you can add them all to your build by adding a line that recursively walks through this directory and adds all files. Your app should then be able to reference these files.
a = Analysis(
...,
datas = [(os.path.join(dp, f), dp) for dp, dn, filenames in os.walk('./resources') for f in filenames],
)

Python unable to move directories using shutil

I'm trying to write a script where it will move a directory (containing images to be processed) into another dedicated working directory (within the project folder) by using shutil.move().
However, my Python script keeps on failing to achieve this by throwing an [Errno 2] No such file or directory: '/Users/user/Desktop/Captured\\ Images' exception.
The target directory is being perfectly recognised so that's not the issue.
I'm currently using macOS to develop this script, and using standard BASH.
This is how I input the path of the source directory (by dragging the folder into the terminal): /Users/user/Desktop/Captured\ Images.
This is how Python interprets the source directory: /Users/user/Desktop/Captured\\ Images.
The script works perfectly when I modify the source path to: /Users/user/Desktop/Captured Images.
I've also tried using the Pathlib Module to prevent file separator issues, but that also didn't work.
I know for sure that what's causing the problem is the \ within the file path since the folder is named 'Captured Images' with a space between it, thus Captured\ Images.
Here's the following source code:
move_directory(input("Please Input The Directory Of The Captured Images You Would Like To Import: "))
def move_directory(source_directory):
try:
shutil.move(source_directory, os.path.dirname(os.path.dirname(__file__)) + '/Captured Images/Source Images')
except OSError as errorMessage:
print("Failed To Move Directory: {0}".format(errorMessage))
Update 1:
I've just tried to move the directories by using subprocess.run(["mv", ...]) and it worked, so now I see that it's not how the script is taking in the input, but a problem between the path input and shutil.move().

Files missing after batch-renaming through python (os.rename)

I wrote a python script to rename all the JPG and jpeg files present in a particular folder.
I changed my directory to the folder which contained all the jpg, JPG files and a rename.py ( which is the script that I wrote ).
import os
cwd=os.getcwd()
for file in os.listdir(cwd):
i=1
if file.endswith('.JPG') or file.endswith('.jpeg'):
new=str(i)+'.JPG'
os.rename(file, new)
i+=1
After running the script all the JPG and jpeg files went missing.(Edit:except 1.JPG)Why did this happen and how do I recover the files?

Python/Pyinstaller - onefile executable

In order to create a python .exe file I have been using pyinstaller and this command:
pyinstaller --onefile -w -i favicon.ico "program.py"
This creates a /dist folder which contains the generated .exe file.
The problem is that I am not able to run this .exe file without including the following program files inside the .exe launching folder.
+ Dir
- favicon.ico
- logo.gif
- data.csv
- program.exe
How can I include the .ico, .gif and .csv INSIDE the .exe so it truly becomes "onefile"?
I'm quite new to python so I apologize in advance if the code is a little chaotic. I faced a similar problem with .csv files. I managed to pack them into .py files by once running this code:
import csv
myfinalvariable=[]
with open(PathToOriginalCsv + '\\' + 'NameOfCsv.csv', newline='') as csvfile:
myfirstvariable = csv.reader(csvfile, delimiter=',', quotechar='|')
for line in myfirstvariable:
myfinalvariable.append(' '.join(line).split())
pyfile=open('PathToDesiredFile\mynewfile.py', 'w')
pyfile.write('newcsv=%s' %(myfinalvariable))
pyfile.close
You can iterate this if you have multiple csv files. Now you have the py file with 'variables' and you can 'forget' about the csv files. Because if you put the created py file into your 'project folder' and put:
from mynewfile import newcsv, newcsv2, ...
into your code, you can modify your code to use the variables 'newcsv', 'newcsv2', etc. instead of loading the original csv files. When you use pyinstaller with the --onefile parameter, it packs the 'mynewfile.py' file into the created exe file. Pyinstaller 3.0 also packs the .ico file when using the parameter --icon=favicon.ico. Tested on Windows, Python3.4, Pyinstaller3.0. I understand this is an old question, I hope this helps someone who stumbles upon it.
By writing a shell script, that can be executed by powershell,
The file can be made and written as a .exe file
The other files can be moved into the new directory.
Now all that needs done is having the Powershell script to run.
You can package the files with pyinstaller's --add-data option. For example with your files you should try:
> pyinstaller --onefile -w -i favicon.ico "program.py" --add-data "favicon.ico:favicon.ico'\
--add-data "lgog.gif:logo.gif" --add-data "data.csv:data.csv"
On other OS it may be required to replace the \ with a ^ (or do it all on one line.)
This should package all the files into the exe.
If you want to access these files from the code you need to add a little bit extra, otherwise the program will not find them.
import os, sys
def resource(relative_path):
if getattr(sys, 'frozen', False):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath('.'), relative_path)
When pyinstaller compiles a script it sets the _MEIPASS variable to the temporary path of the created files at run-time. This script harnesses that to locate these file and defaults back to the ordinary path in un-compiled mode read more.
To access the files from the code, just replace all links to the files with resource('myfile.etc'). For example, using youe data.csv file
with open(resource('data.csv'), 'r') as csvfile:
# do stuff

Categories