pyInstaller exe failed because it did not include a module - python-3.x

Situation: Building an EXE from a python script that encrypts things.
Problem: The EXE always fails as it cannot find modules that I have imported (Crypto).
Question: Is there a flag I need to turn on or include to make sure that pyInstaller includes Crypto when building the EXE?
Additional information: The Crypto here refers to pycryptodome

You have to edit your .spec file to include the hiddenimports. As shown here:
hiddenimports=['pycryptodome.apps'],
Run pyinstaller with the .spec command afterwards pyinstaller --name=appname appname.spec
Then you'll have to add the modules that are in your site-package to the root dist application folder. Just copy and paste the entire folder.

Related

How to distribute python based software on Linux based OS

condensed version of what I want to achieve:
Create .rpm and .deb packages from my source.py source code and make sure all dependencies get resolved when installing them on an deb/rpm based linux distribution.
More details:
Let's assume I have created a piece of software which is located in a folder structure like this:
---MyProgram Folder
---MyProgram Folder
---img Folder
---logo.ico File
---media Folder
---head.txt File
---__init__.py File
---source.py File
---a.py File
---LICENSE File
---README.md File
---setup.py File
The file setup.py contains the following:
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name="MyProgram",
version="0.0.1",
author="First Last",
author_email="email#memore.com",
description="A tool to create nice things",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://google.com",
packages=setuptools.find_packages(),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
python_requires='>=3.7',
data_files=[
('.../MyProgram/img/logo.ico'),
('.../MyProgram/media/head.txt'),
],
)
I now run
python setup.py sdist bdist_rpm
from a cmd line under '.../MyProgram'. Two folders 'dist' and 'build' are created as well as 'MyProgram.tar.gz' and two rpm's 'MyProgram-noarch.rpm' and 'MyProgram-src.rpm'.
When i try to install 'noarch.rpm' under fedora 31 the process end successfully but no "shortcut" is created, and when i type MyProgram in a cmd line it is not found.
rpm -ql MyFilter
does find it and outputs a bunch of paths:
/usr/lib/python3.7/site-packages/MyProgram/...
/usr/lib/python3.7/site-packages/MyProgram/source.py
/usr/lib/python3.7/site-packages/MyProgram/a.py
....
Which tells me that my installation at least has copied the basic filesystem. But i also see that all the original .py files are still .py files.
My questions:
How can i 'make' the rpm so that all dependencies are contained inside the rpm, or at least get resolved by dnf/apt/yum when installing the rpm? In other wording: Is it possible to bundle all dependencies into a rpm/deb like in an .exe for example?
How can i specify a path like '/usr/bin' or 'usr/share' as installation target
dir?
How can i add a launcher app bundled into the rpm/deb?
Is the above a good way of doing this at all?
If the solution to this is trivial and i just overlooked it i am really sorry to bother you but atm i just can't see it. Sites that have relevant information and that i already reviewed:
https://docs.python.org/2.0/dist/creating-rpms.html
https://github.com/AppImage/AppImageKit/wiki/Bundling-Python-apps
Python 3.5 create .rpm with pyinstaller generated executable
https://github.com/junaruga/rpm-py-installer
https://www.pyinstaller.org/
https://packaging.python.org/overview/#python-source-distributions
https://packaging.python.org/overview/
https://pyinstaller.readthedocs.io/en/stable/usage.html
https://pyinstaller.readthedocs.io/en/stable/installation.html
https://python-packaging-tutorial.readthedocs.io/en/latest/setup_py.html
Just my two cents, rather than a complete answer. Will mostly touch on RPM packaging.
The bdist_rpm option seems easy, but you have little control of the logic of the .spec file it generates/uses and cannot do fancy stuff like scriplets, etc.
That is, unless you take the approach of having it generate the .spec file and quit (instead of building final RPM). From the docs:
If you wish, you can separate these three steps. You can use the --spec-only option to make bdist_rpm just create the .spec file and exit; in this case, the .spec file will be written to the “distribution directory”—normally dist/, but customizable with the --dist-dir option. (Normally, the .spec file winds up deep in the “build tree,” in a temporary directory created by bdist_rpm.)
But as a matter of preference and consistency, I would advise on following distro-specific guidelines for packaging Python apps.
In that way, you will be more in line with the distro's you are building for.
It is not the easiest way though. You will have to shift through some docs. Basically, if you're building for anything CentOS/RHEL, Fedora guidelines for packaging should be observed.
You can find the extra reference here, with the example .spec file for building both Python 2 and 3 versions of the same app.
For this whole 'build like a distro' thing, you would definitely want to look into using mock for the job, to build your package in a chroot.
As for the "shortcut" issue, you have to have your setup.py declare some console scripts for it to create one when you install your package. E.g. from lastversion's setup.py:
entry_points={"console_scripts": ["lastversion = lastversion:main"]},
This entry will result in a "binary" lastversion created/installed (which runs the defined function) when you install your Python package.
Subsequently, in the spec files, the macro %py2_install will make use of setup.py to create the same launcher program.
And you will then be able to ensure that launcher is packaged by placing it in the files section of the spec file:
%files -n python3-myapp
%license COPYING
%doc README.rst
%{python3_sitelib}/%{srcname}/
%{python3_sitelib}/%{srcname}-*.egg-info/
%{_bindir}/myapp

Hide input files during the conversion of python scripts into exe

I have python scripts in folder A and some dependent input files (.xlsx,.txt) in folder B.
I am using cx_Freeze to convert them into exe.
I have the files in the folder B as a list in include_files in setup.py
During the conversion, the files fall in the build folder.
The files should not be visible to the user, or at least they should be only in read-only mode.
You can use os.chmod at the end of your setup script to make any file of the build directory read-only. For example:
import os
import stat
os.chmod(path_to_file, stat.S_IREAD)
Of course you need to know the path to the build directory. You can also tell cx_Freeze which directory to use as build directory by using the build_exe option of the build_execommand, see the cx_Freeze documentation.

Making an Executable out of an entire Python Project

Is there any way I can make an executable out of my Python project? There are many Python scripts that are in my Project and there are SQLite db files as well as other files and folders that are required for the software to run correctly. What is the best way of making this entire project executable?, Should I only make the Python scripts executable?
I have tried Pyinstaller but I am not sure how to bundle all the files into 1 single executable. Shown above is a copy of all the files and folders in my directory.
I think you need to modify the spec file, which PyInstaller creates on a first run. There is a special parameter for data files:
binaries: non-python modules needed by the scripts, including names given by the --add-binary option;
Try adding your database and other data files to this field and they should be included to you package.
For further question I recommend to refer to official documentation and check examples on Github

.pyc not generated while creating module

I am trying to create a python module but a .pyc file is not created. I am working in windows. I execute 2 commands in command prompt(which I run as administrator) as following:
c:\Python33\python.exe setup.py sdist
after this statement is executed in the same window I execute
c:\Python33\python.exe setup.py install
I don't know what I am lacking???
Python3.x doesn't create .pyc files in the same directory. This is part of python3's __pycacahe__ standard. Instead, your .pyc files are stored in __pycache__ for the version that you build for.
This was mentioned in Brett Cannon's talk at Pycon-2013

Why does my pyinstaller created executable require admin privileges?

I've written a Python program which I distribute using pyinstaller. I've been using the onefile option so far to create a standalone executable. That's been great up until now, but as the application has grown the startup time is getting a bit long. I'd also like users to install the application properly to make upgrading simpler.
I've been trying to create a single directory version of the app using pyinstaller's onedir option. However, the resulting .exe file that is created requires admin privileges to run, which the onefile version did not. The program itself doesn't need any such privileges so I assume this is something that pyinstaller is doing. How do I create an application that doesn't require admin privileges?
Additional info:
Python 2.6, pyinstaller v1.4
Application uses PyQt4 and pygame modules.
Trying to create executable for Windows 7.
Using -w pyinstaller option to create a windowless executable.
admin privileges could be asked in few cases:
A. if the executable name contains relevant keywords (like setup, install, update or patch)
B. the application requests it in it's manifest.
C. the .exe file name do not match the name in the manifest file.
if you create a .spec file for your application package, you can add
exe = EXE(
...
manifest=None,
...
)
and it won't ask for password, unless you rename it to setup or install.
I have recently run into this issue, and my experience in solving it was thus:
PyInstaller with --onefile option creates a manifest file in the 'executable'. This manifest file on Windows tells the OS a few things about the application it is bundled with. One of the things it specifies, is the application name/manifest file. The format of the manifest filename is appname.exe.manifest. If your program is frozen with PyInstaller, the executable name that it stores in the manifest will be the name given to the completed EXE under the /dist folder of PyInstaller. IF you rename the EXE, the manifest file packed with it is no longer matching! Therefore, create a manifest file with the same name as the final EXE filename and run PyInstaller with the --manifest option, OR don't rename the EXE that PyInstaller creates.
When you package the PyInstaller project with the custom --manifest, the renamed program no longer requests administrator elevation.

Resources