py2exe trouble for multiple scripts - python

I am working on a project on python. I have divided my complete script into 4 modules to make the code better understandable. I need to create a exe of the code which holds the gui.
The problem is that different modules have different dependencies.One module requires pyusb, one requires PIL and other requires scipy. How do i make sure that making an exe of one code itself is sufficient to handle all the dependencies. I dont mind making a single exe from multiple codes. Please help

You can specify list of packages to include (along with subpackages) as value to the key package
and list of module names to include as value to the key includes in the options dictionary that can be passed to py2exe. Check this py2exe help page for list of options that one can use to configure py2exe.

By default py2exe should include all your imports into the bundle, but if this doesn't work, you can try false-importing the modules you need. you can do this in the main script that you are passing to py2exe:
in your main script:
if False:
import <module x>, <module y>, <module z>, <etc...>
This should make py2exe see the modules right away, and include them with your bundle.

Related

Dynamically importing .py files after compiling

I've tried looking online and I'm honestly lost at this point.
I'm trying to find if there's a way to import python scripts and run them AFTER my Python program has been compiled.
For an example, let's say I have a main.py such that:
import modules.NewModule
a = NewModuleClass()
a.showYouWork()
then I compile main.py with pyinstaller so that my directory looks like:
main.exe
modules/NewModule.py
My end goal is to make a program that can dynamically read new Python files in a folder (this will be coded in) and use them (the part I'm struggling with). I know it's possible, since that's how add-ons work in Blender 3D but I've struggled for many hours to figure this out. I think I'm just bad at choosing the correct terms in Google.
Maybe I just need to convert all of the Python files in the modules directory to .pyc files? Then, how would I use them?
Also, if this is a duplicate on here (it probably is), please let me know. I couldn't find this issue on this site either.
You may find no detailed answer simply because there is no problem. PyInstaller does not really compile Python scripts into machine code executables. It just assembles then into a folder along with an embedded Python interpretor, or alternatively creates a compressed single file executable that will automatically uncompress itself at run time into a temporary folder containing that.
From then on, you have an almost standard Python environment, with normal .pyc file which can contain normal Python instructions like calls to importlib to dynamically load other Python modules. You have just to append the directory containing the modules to sys.path before importing them. An other possible caveat, is that pyinstaller only gets required modules and not a full Python installation, so you must either make sure that the dynamic modules do not rely on missing standard modules, or be prepared to face an ImportError.

How to package a Python 3 console application as a windows binary?

I am doing this practice project to implement a LISP interpreter in Python, using help from here. I wanted to create an exe file for the project, executing which would start a REPL.
I tried using py2exe and pyInstaller but an error is thrown when I execute the output binary, saying that this script cannot run.
Where did I go wrong with my approach and what alternative ways can I use?
Thank you.
It is hard to know for sure but have you checked that all of the required dependencies for your project are either in the same folder as the created executable or (at least) in your path?
The other alternative that I am aware of (and use) is cx_Freeze. This particular exe builder has cross platform support.
cx_Freeze will attempt to automatically find all dependent python modules and include them in the final build. I imagine that the other two options work in the same manner. Packages that cannot be automatically located and binary dependencies (eg dlls, sos) must be explicitly specified in the build configuration scripts.
One method I have for debugging for missing dependencies is to manually copy the suspected missing dependency into the same folder as the .exe to see if it fixes the issue. If it does then I will specify it in the build configuration script.
See https://cx-freeze.readthedocs.io/en/latest/distutils.html for cx_Freeze documentation, in particular section titled build_exe.
Here is a good example of a non-trival setup.py for cx_Freeze: http://www.pythonexample.com/code/cx_freeze-setup/

Importing external module in single-file exe created with PyInstaller

I am using PyInstaller to create a single-file executable. Is it possible for my script to perform an import such that i) the imported module is imported from the same directory as the exe (i.e. it's not packaged into the exe) and ii) that imported module can import other modules that were packaged into the exe?
The background here is that the imported module contains configuration that the user should be able to modify. This may include creation of custom derived classes and use of enums from the packaged modules.
I haven't found any advice on this, though it's a difficult search because there are so many similar topics that use basically the same keywords.
The following steps allow a Python module (named external_module here) outside of an executable created by PyInstaller to be imported and for that module to import modules that were bundled into the executable.
Add excludes=['external_module'] to the Analysis object used in the PyInstaller spec. This prevents external_module.py being bundled into the executable.
Add sys.path.append(os.path.dirname(sys.executable)) where external_module is imported in your application. This allows it to be imported from the directory the executable is in, which is different to the directory that the application will run in (due to being decompressed to a temporary folder). See below for my recommended method of achieving this.
Make sure any imports performed by external_module.py are also performed by one of the bundled modules before external_module.py is imported. The interpreter will not resolve the external module's imports against bundled modules, but will use ones that already exist in sys.modules.
In order to set up the paths correctly you can use the following:
if getattr(sys, 'frozen', False):
app_path = os.path.dirname(sys.executable)
sys.path.append(app_path)
else:
app_path = os.path.dirname(os.path.abspath(__file__))
frozen is only available in generated executables, not when running as a script directly. This snippet will add the executable's location to sys.path if required as well as giving you easy access to the executable or script's location for use in code.
As an example of the final bullet point, consider the following.
# bundled_module1.py
import external_module
# bundled_module2.py
# module content
# external_module.py
import bundled_module2
This will fail in external_module.py because bundled_module2 can't be found. However, the following modification to bundled_module1.py will work:
# bundled_module1.py
import bundled_module2
import external_module
This will be fine if there are a limited set of bundled modules that the external one should be able to import. It may get unwieldy for larger sets.
Given that the documentation states that the interpreter will resolve imports against modules bundled into the executable, this feels like a possible bug. Interoperating with modules outside of the executable isn't explicitly called out though.
Type in Pyinstaller -h. It will give you info about pyinstaller and tell you about --runtime-hook. I presume adding this to the executable should work. There's actually a whole page of documentation for this. Surprised you could not find that.
Anyway,
The docs say put in:
pyinstaller --additional-hooks-dir=. myscript.py.
I presume then something like pyinstaller --additional-hooks-dir=C:\pathtofolder myscript.py should work in theory. Yet to test it. Tell us how it goes and what made kinks made it work for you.
Lastly, if you want to be hipster try integrating cython for speed and obfuscation. Fair warning, cython is not as user friendly as pyinstaller appears to be. I have yet to use it successfully.

How to properly create a pyinstaller hook, or maybe hidden import?

I have two packages (say, dataread and datainspector) that were somehow not detected by PyInstaller. Because of this, the application terminates when the running application reaches the point where it needs to import modules from those packages.
The easiest solution would be to copy dataread and datainspector into packaged app. But this will break the intention of packaging a binary version of the application.
I've read about hidded imports and hook, and I think that both can solve the problem, but I am not sure of which one to use.
Any suggestions?
PS: both these packages may contain nested directories.
Hooks are files that specify additional actions when PyInstaller finds import statements.
If you add a hook-data.py file which contains a line hiddenimports = ['_proxy', 'utils', 'defs'], PyInstaller will check it to find additional imports when it sees import data.
You have to specify the path to the hook directory via --additional-hooks-dir (this is useful if you don't want to mix your source code with compile-only files, and instead keep them in a separate directory).
The simpler solution is to use --hidden-import=modulename along with the PyInstaller script. It will add modulename as import statement silently.
Hooks are better if you want to specify which import needs what additional modules. --hidden-import is simpler as a one-shot or for debugging.
More info - https://pyinstaller.readthedocs.io/en/stable/hooks.html
Use Auto-py-to-exe to add hindden libraries.
In additional files add Rasterio folder (C:/users/Admin/anaconda3/envs/name/Lib/site-packages/rasterio) and then convert to exe.
It worked for me.
if it says some other libraries are missing then add folder of that library too.

py2exe: why are some standard modules NOT included?

My python program uses plugins (python files) which I import dynamically using __import__.
I bundle my python program into a Windows exe using py2exe.
I've just spend searching 2 hours why my plugin python file couldn't be loaded properly from the .exe version. I got an ImportError: "no module named urllib2"
It appeared my plugin was using urllib2 (through an import urllib2 statement), and that standard library module was apparently not bundled into the exe. Other modules used in the plugin (re, urllib, ...) gave no problem, but perhaps they were already references in python files I statically include in my program.
How can I know which standard Python library modules py2exe bundles by default in the exe? (so I know whether I or somebody else can use them in a plugins). The py2exe documentation doesn't give an hints, except for saying that it includes a lot of modules from the standard library.
To see which modules are included look inside the library.zip (if there is no library.zip file - then try opening the EXE in any ZIP application - or rename it to .ZIP and try and open it).
You will be able to see a list of *.pyc. You can look at the list of files and directories to get an impression of which modules are included or not.
If you require a specific package to be added - add it to the 'packages' list.
As to why it doesn't include everything or how it chooses to include some and not others? My understanding is that py2exe looks in your code to figure out what you are using and includes those (and some that it probably needs itself) but maybe it also has some heuristics to add other modules too (I haven't checked :)

Categories

Resources