Pyinstaller onefile doesn't work on other computers - python

My role at work includes automating several processes which are easily automated via Python, for use by the entire team at the office. None of my coworkers have Python set up on their devices (we're all Windows) nor would they be comfortable using it if they did, so I've been compiling my work into .exe files with tkinter.
My most recent (and, of course, the most important) program compiles into a onefile .exe without issue, and runs perfectly on my computer. My coworkers are able to open it and load files into it, but when they go to activate some of the tkinter buttons within, one coworker has absolutely nothing happen while another gets a windows error message that the program has crashed. I'm unable to recreate these issues on my side.
The .exe was made using pyinstaller in a virtual environment, in which I installed all necessary dependencies. The script does not need to read or reference any other files in order to run. Is it possible that the .exe is still somehow missing a dependency that it's finding on my device and not others? How can I be sure? Would setting it up to include an installer wizard make a difference? Thanks for the help on this!
I can't include the full script due to character limit, but I've included the opening lines with all imports.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.fft import fft as fft
from scipy.fft import ifft as ifft
from tkinter import *
from tkinter import ttk
from tkinter import simpledialog
from tkinter import filedialog
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

Related

How do I change the backend in CoCalc to show a matplotlib scatter graph?

I have a program that is working fine locally, but I need to use it in CoCalc on the cloud to share with a group. Everything works fine until the end, when I want to create a scatter graph, in standard way. There are a bunch of other specs, but essentially, it's just
plt.scatter(x, y, color = 'blue')
plt.show()
Nothing tricky. But in Cocalc, it tells me "UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure."
Here are the imports from the beginning of the file:
import nltk
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
I've searched for this error and tried the solutions I've found, such as importing tkinter. So, for instance, if I change the headers to
import nltk
import tkinter as tk
import pandas as pd
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import numpy as np
I get a different error: "Cannot load backend 'TkAgg' which requires the 'tk' interactive framework, as 'headless' is currently running."
I've seen instructions about pip installations and such, but a) I'm not sure the installations would make everything work for my group, and b) CoCalc generally has most of the standard packages ready to go, so maybe that's not the problem?
Obviously, I'm not experienced with these issues, so help is much appreciated.
If you're using a Jupyter notebook in CoCalc, then the above will just work fine. Here's an example:
https://cocalc.com/wstein/support/matplotlib-scatter-in-jupyter
If you're writing all of your code as part of a Python program (so, e.g., .py files) and running this from a Terminal, CoCalc will also fully support Tk and this working! However, you have to start a new X11 desktop session in CoCalc by clicking +New --> "Linux Graphical X11 Desktop", then run your Python program from the terminal in the upper left. You'll see any windows that pop up in the main window off to the right.
See https://cocalc.com/wstein/support/scatter-matplotlib-x11

Can I exclude unnecessary imports after import all modules?

I'm using tkinter package for GUI programming.
Since I don't know what modules are in need during coding, I usually import all. (by typing from tkinter import *)
But I found this could cause a problem when I turned a .py file into .exe file by using pyinstaller. The result file size was too large.
To reduce the file size, I'm trying to edit the .py file by excluding unnecessary imported modules. There are lots of unused imports confirmed by pylint(it just warned me when I run .py file in terminal on Visual Studio Code). But how should I type the code to exclude these imports?
While importing from other modules its always better to import only the classes and functions that you need or else your program could face problems like taking a lot of time to run the program and takes up a lot of storage space etc.
To only import the classes and functions you need you can use
from module_name import function_name, class_name
Or else you can import tkinter itself and use the module name to access the classes and functions in it like this
import tkinter
window = tkinter.Tk()
To know more about modules you can check the documentation Modules - Python 3.9.0. And for tkinter tutorials you can checkout Tkinter Tutorials

Pyinstaller onefile Executable Incredibly Huge and Slow

I know I'm not the first to ask, but the other answers on the forum could not help me, so I'm asking. I have a short (181 line) python script that only has the imports
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, RadioButtons
and runs up a interactive math tool with sliders and radio buttons. But when I built it with pyinstaller, I end up with a massive (90 MB) dist folder that appears to include all sorts of unnecessary packages like babel and cryptography. The executable inside takes around 5 seconds or so to actually display the figure. When I run it with the --onefile option, things seem no better, as I get a 43 MB executable that takes even longer, about 10 seconds, to display the figure.
I'm prety sure it's not the script's fault because in Spyder, it takes less than a second to open up. I'm suspecting that it is because of all the extraneous packages. If so, how do I get pyinstaller to exclude them, and if not, then what is the likely issue? Thanks.
EDIT: Also, I am doing all of this in a conda virtual environment, which I read somewhere should already help to make pyinstaller's executable smaller. After creating the environment, the only packages I directly installed were pyinstaller, spyder, numpy, and matplotlib.
This happens because when creating the executable you are also using the libraries, what I do is import only what is necessary for the program and then compile it, for example, for an application in Tkinter:
from tkinter import Tk, Label
root = Tk()
Label(root, text='Label').pack()
root.mainloop()

Package a GUI for distribution - ghostscript..?

I have a GUI created that I'd like to ship out to people I work with. The GUI works perfectly for me, but when I packaged it using pyinstaller and --onefile, it didn't work for anyone else. I am aware no one else has python installed on their machines, but I was told that wouldn't be a problem. However, my program involves ghostscript.
In short, my program has 3 buttons. Button 1 allows the user to select a pdf. Button 2 will convert this pdf into images. Button 3 will read each image and say whether it is a colour page or a black only page, when done it'll delete the temporary image files.
the imports i am using are
from tkinter import *
import os, time
from PyPDF2 import PdfFileReader, PdfFileWriter
from tempfile import NamedTemporaryFile
from tkinter.filedialog import askopenfilename, askdirectory
import tkinter.scrolledtext as tkst
from PythonMagick import Image as IMG
from PIL import Image
I think I'd somehow need to have the user install the same version of ghostscript as me when they open the application. Does anyone have any advice on how I can sort this out to have people use it?
EDIT: When I say 'it didn't work for anyone else', i mean the application opened, the user could select a file, but the button which runs the ghostscript stuff didn't work. Meaning ghostscript needed to be installed. After installed it worked.
I would suggest manual installation of GhostScript and adding its path to the OS environment.
import os
from pathlib import Path
this_path = Path(sys.argv[0]).parent
os.environ['MAGICK_HOME'] = ';'.join([str(this_path / 'image_magic'),
str(this_path / 'GhostScript' / 'bin')
])
Here, I install Image Magic + GhostScript in the root with the Python files.

Building wxpython exe using PyInstaller

I am trying to build an exe using PyInstaller (with Python 2.7) and have been stumped. My python code uses the modules wx, matplotlib, basemap (a part of matplotlib), and pylab. There are others, but these seem to be the main ones.
I have installed PyInstaller and then i did:
python pyinstaller.py C:/Python27/Convertthisfile.py
It goes through the whole process, but when i try to run the final executable, it comes up with the error:
"No module named PyQt4.QtCore"
I have installed PyQt GPL 4.9.1 for Python 2.7. However, I have no idea where PyQt is even being used in my code. I don't specify it anywhere that i know of.
Anyone have any thoughts? Nothing I do seems to work. I have even tried the GUI2EXE.py -- i can't get py2exe, pyinstaller, or cx_freeze to work.
HELP!
I have added my code below to hopefully help. To answer the comments, yes, my code is located in C:\Python27. I have no problem "building" it with pyinstaller, but the above error comes up when i try to run the given executable. I have searched the code and do not see any use of PyQt4.
When i run cx_freeze, i have issues with the basemap data files -- they do not seem to be included in the ".zip" when i build it. Also, none of my modules seem to get included either.
Here is what i import for my code (some of these functions are my own -- mainly the last ones listed).
import wx
import time
from matplotlib.backends.backend_wx import FigureCanvasWx as FigureCanvas
from mpl_toolkits.basemap import Basemap
from matplotlib.figure import Figure
from datetime import datetime
import wx.calendar as cal
import wx.lib.mixins.listctrl as listmix
from pylab import *
from decimal import *
import adodbapi
import annote_new
import cPickle as pickle
import calc_dist
import Game_Score
import Calculate_Distance
import Duplicate_Finder
import copy
Hopefully this clears things up?

Categories