I'm trying to package a cli application using pyinstaller (currently for macos). My initial impression on reading the pyinstaller documentation is that I would be able to bundle all necessary files into a single file when the --onefile option is used.
However, when I bundled the file with the following command and tested it on someone else's pc, the resulting binary had a dependency to a path on my PC (specific to the bundled venv configuration). (Locally the bundled onefile binary runs fine... I assume because the path dependency is present)
pyinstaller mycli.py
Am I miss-understanding what pyinstaller does? Or, is there something special I need to do to make the resulting bundle portable?
Using python3 btw
You can use the tool dependency walker to identify the missing files (in case of libraries: dll, pyd) that need to be bundeled with your exe.
These files need to be added to spec file, as described in the docs.
Related
I am using Tesseract OCR for my program and I am going to convert it into a single .exe file using pyinstaller. The problem is that in order for Tesseract to work, I need to reference the path to the program installed on my computer, like this: pytesseract.pytesseract.tesseract_cmd = 'E:\\Tesseract-OCR\\tesseract'
Since this is not just a separate library that can be imported, but a standalone program, I can't pass it to pyinstaller as an '--add_data' argument. How do I make a one-file executable then?
Assuming you're on Windows, I ran into this problem and think I solved it by compiling a static version of tesseract (which does not need to be installed) and including its path as a binary in the pyinstaller spec file.
Official compiling instructions here:
https://tesseract-ocr.github.io/tessdoc/Compiling.html#windows
Install MS Visual Studio 15 (with c++) and vcpkg and execute one of the following through command prompt:
for 64-bit:
vcpkg install tesseract:x64-windows-static
for 32-bit:
vcpkg install tesseract:x86-windows-static
The tesseract executable will be located a few subfolders within the vcpkg folder on your PC. With that file, you also need to download a .trainneddata file and place it within a folder called 'tessdata' in the same directory with the tesseract exe.
Create a pyinstaller spec file and edit the Analysis(binaries=[]) section to include the folder path where tesseract is located (if you're not using a subfolder for tesseract I think you'd need to add both tesseract.exe and the tessdata subfolder). I also changed inclide_binaries=True
Run pyinstaller and include the option --specpath 'yourspecfile.spec'
I haven't yet attempted to try it on a different PC, so haven't fully tested that it works as intended (I don't know anything about compiling c++, there may be additional files/links needed for tesseract that are still intact since I've only been testing on the build PC)
#Zstr33's answer is correct, but it lacked detail. Following instructions have been tested on Windows 10 64-bit. Link to official compiling instructions here: https://tesseract-ocr.github.io/tessdoc/Compiling.html#windows.
Steps:
Install Visual Studio. Make sure to install the below items:
Then, click on individual components.
Then, select the following.
You can add whatever other components you want, but those are the ones that are needed to compile tesseract into a static binary. Also, if you don't use English, click on the language packs tab and add the English Language pack, this is needed for vcpkg.
Follow the quick start guide for installing vcpkg, found here: https://github.com/microsoft/vcpkg#getting-started.
Navigate to where you copied the vcpkg directory, or add it to path. Then run: vcpkg install tesseract:x64-windows-static for 64-bit, or vcpkg install tesseract:x86-windows-static for 32-bit.
Go to place where you put the tesseract directory\tesseract_x64-windows-static\tools\tesseract for 64-bit, and place where you put the tesseract directory\tesseract_x86-windows-static\tools\tesseract for 32-bit.
To use with pyinstaller, using --onefile.
I built my application exe using Tesseract and EasyOCR with the following command, hope this helps.
python -m PyInstaller --paths "fullpath-to-custom-libraries" --add-data "C:\Program Files\Tesseract-OCR;Tesseract-OCR" --collect-all easyocr --onedir -w main.py
I did get it to run with Pyinstaller after all.
First, I needed to create 2 Hook files as described here:
https://github.com/jbarlow83/OCRmyPDF/issues/659#issuecomment-714479684
Then, when running the exe, I still got an error missing pikepdf._cpphelpers
To solve that, just add
from pikepdf import _cpphelpers
in your python file as described here:
How to fix a pyinstaller 'no module named...' error when my script imports the modules pikepdf and pdfminer3?
My Pyinstaller call looks like that:
pyinstaller --onefile appname.py --paths="C:\python\anaconda3\envs\appname\Lib\site-packages" --additional-hooks-dir="C:\coding\appname\Hooks"
since bundling everything up with pyinstaller could be a real pain, I did the following steps:
Imported Pytesseract in my script
created the Exe file with pyinstaller (without defining anything in my spec file)
bundled Tesseract-Ocr installer and my script.exe with an external installer creator.
So the final user will have both the tesseract installer and tesseract.
With the external installer you have a lot of freedom and you can also play with the path variable.
I tried with pyinstaller and ocrmypdf forever and did not get it to work. I ended up using Nuitka. Worked right from the start :-)
Use sth. like:
python -m nuitka --mingw64 --standalone --follow-imports yourapp.py
http://nuitka.net/doc/user-manual.html
There was a similar answer here somewhere already, just could not find it anymore to link to it.
So I can use PyInstaller to make a one-file executable and to make a standard executable among other files in a folder.
But how do I turn Python files into an MSI installer so that it's fool-proof where it makes a shortcut on the desktop? (For distribution so that it isn't required for the user to have Python installed)
(When I say Python files to an MSI installer I mean the regular PyInstaller to folder output but with a way of getting a shortcut to the executable onto the desktop very easily for a regular user)
(It doesn't have to be PyInstaller if there's an alternative).
Pyinstaller does not intergrate such a tool.
You could get a third party installer (some suggested here How to create a robust, minimal installer for Windows?) and add your output exe to it and install that way, if you choose the right tool you will be able to add to desktop (plus a lot of other actions such as adding to path ect).
Or you could use cx_Freeze which has it built in. When running the setup script just add the bdist_msi flag.
It can add to shortcut desktop but is fairly limited in other ways (or you may need to perform some hack).
To add to desktop with cx_Freeze see Use cx-freeze to create an msi that adds a shortcut to the desktop.
You can use Inno which creates a shortcut on the desktop and start menu. Also, it is located in the program directory of windows. it means that you can install/uninstall it like other programs or applications.
Inno website:
https://www.jrsoftware.org/isinfo.php
A tutorial on how to use it on youtube:
https://www.youtube.com/watch?v=DTQ-atboQiI
I want to make a portable app that would have some code and python executable that would run on any Windows even if python is not installed.
I would like it to be python 3.6 and so it has only pip and setup tools installed.
EDIT: concerning duplicate
not quite. I don't want to compile the code. I wanted to give them .py files but realize that Windows won't have python installed on default. I want something that can be carry on a flash drive but will run my code from source not binary.
Please correct me, if I understood it wrong. I think there are at least two ways to do it.
suppose you have one portable_run.py script you want to run everywhere on a flashdisk.
Make a exe file with pyinstaller for example. you can get a exe file like portable_run.exe. On target windows system what you need to do is to run the exe direcltly protable_run.exe
Use a portable python distribution like winpython or python-xy. you just need to copy this portable distribution on the flash disk together with your portable_run.py. To run it on target system flashdisk/path-of-winpython/python portable_run.py
Hopefully it could give you some idea.
I also encountered the same problem and managed to create a portable python with Python's official Windows embeddable package.
I wrote the steps into a ps1 script so I can easily repeat the process without going through the pain.
The steps:
Download the portablepy.ps1 from the repo :
https://github.com/Dreamsavior/portable-python-maker
Create a blank folder, put the portablepy.ps1 to that folder.
Execute the portablepy.ps1
The script will create a portable python 3.9.10 with pip in the current folder by default.
To install custom version of Python run the script with -source and -destination parameter
.\portablepy.ps1 -source "https://www.python.org/ftp/python/3.9.10/python-3.9.10-embed-amd64.zip" -destination "C:\SomeDir\PortablePython\"
Where the -source is the url of the Python's Windows embeddable package from this page: https://www.python.org/downloads/windows/
And -destination is the path of your folder (ended with backslash).
env: linux, python2.6, pyinstaller2.0
target: to specify where to find the .so libs after compiled / moved to other folder
I use to compile my server side python source code using
pyinstaller -F --noconsole --out=/bala /bala.py
but this requires to extract the packed .so to system
/tmp/_MEI*
when run the all in one exe, which is not allowed, so I just remove the '-F' tag, to be
pyinstaller --noconsole --out=/bala /bala.py
this works fine, but all .so files were at the same folder with the binary program, like libpython or zlib,
I somehow prefer the layout to be
root/exe/my_program
root/lib/all_so_lib
obviously, the .so are no longer at it's '.' folder
as expected, It does not work by default, says
Python library not found
Segmentation fault (core dumped)
I've tried to specify LD_LIBRARY_PATH, PATHONLIB, PATHONPATH, and even PATH, both not work.
Here I want to ask if this is possible, if so, how?, to specify environment variable at runtime, or to add some parameter when freeze the code? I'm just a normal user and has no rights to touch /usr/lib/
I want to add Python as a scripting language to my game. If instead of distributing PY script, I distribute the PYC compiled files with my game, will the user still need Python installed, or will the DLL be sufficient?
Not only would they still need the Python interpreter, but the compiled python byte-code files are not guaranteed to work across different platforms.
You do need an executable to actually load the files into the VM. Fortunately it doesn't need to be very complex.
pyinstaller can be used to convert the .py file into an executable file
to install the pyinstaller
pip install pyinstaller
and to convert the .py file let's say file.py
pyinstaller file.py
this will make two new folders in the same directory
build and dist. dist folder contains all the required dll and file.exe to run the python code without python installed.