Ive been tinkering around all day with solutions from here and here:
How would I combine multiple .py files into one .exe with Py2Exe
Packaging multiple scripts in PyInstaller
but Its not quite working the way I thought it might.
I have a program that Ive been working on for the last 6 months and I just sourced out one of its features to another developer who did his work in Python.
What I would like to do is use his scripts without making the user have to download and install python.
The problem as I see it is that 1 python script calls the other 14 python scripts for various tasks.
So what I'm asking is whats the best way to go about this?
Is it possible to package 15 scripts and all their dependencies into 1 exe that I can call normally? or is there another way that I can package the initial script into an exe and that exe can call the .py scripts normally? or should I just say f' it and include a python installer with my setup file?
This is for Python 2.7.6 btw
And this is how the initial script calls the other scripts.
import printSub as ps
import arrayWorker as aw
import arrayBuilder as ab
import rootWorker as rw
import validateData as vd
etc...
If this was you trying to incorporate these scripts, how would you go about it?
Thanks
You can really use py2exe, it behaves the way you want.
See answer to the mentioned question:
How would I combine multiple .py files into one .exe with Py2Exe
Usually, py2exe bundles your main script to exe file and all your dependent scripts (it parses your imports and finds all nescessary python files) to library zip file (pyc files only). Also it collects dependent DLL libraries and copies them to distribution directory so you can distribute whole directory and user can run exe file from this directory. The benefit is that you can have a large number of scripts - smaller exe files - to use one large library zip file and DLLs.
Alternatively, you can configure py2exe to bundle all your scripts and requirements to 1 standalone exe file. Exe file consists of main script, dependent python files and all DLLs. I am using these options in setup.py to accomplish this:
setup(
...
options = {
'py2exe' : {
'compressed': 2,
'optimize': 2,
'bundle_files': 1,
'excludes': excludes}
},
zipfile=None,
console = ["your_main_script.py"],
...
)
Working code:
from distutils.core import setup
import py2exe, sys, os
sys.argv.append('py2exe')
setup(
options = {
'py2exe' : {
'compressed': 1,
'optimize': 2,
'bundle_files': 3, #Options 1 & 2 do not work on a 64bit system
'dist_dir': 'dist', # Put .exe in dist/
'xref': False,
'skip_archive': False,
'ascii': False,
}
},
zipfile=None,
console = ['thisProject.py'],
)
Following setup.py (in the source dir):
from distutils.core import setup
import py2exe
setup(console = ['multiple.py'])
And then running as:
python setup.py py2exe
works fine for me. I didn't have to give any other options to make it work with multiple scripts.
Related
I wrote a basic script in python 3.7 that does what I need. However it needs to run on another person's computer. I want to run this as an exe then just change the icon logo.
I have installed py2exe (I believe). Below is the python script:
pip install py2exe
import os
os.startfile(r"\\ComputerName\c$\users\UserName\desktop\Lullaby wav.wav")
I have another file, that looks like this (basing this off this thread Can I somehow "compile" a python script to work on PC without Python installed? ):
import sys
from distutils.core import setup
import py2exe
entry_point = sys.argv[1]
sys.argv.pop()
sys.argv.append('py2exe')
sys.argv.append('-q')
opts = {
'py2exe': {
'compressed': 1,
'optimize': 2,
'bundle_files': 1
}
}
setup(console=[entry_point], options=opts, zipfile=None)
I then open up cmd and try to use the compile.py file on myscript per the instructions but get an erro:
File "", line 1
python compile.py covid.pyw
^
You can use PyInstaller. Which is inbuilt, if not you can install it. Just very simple lines in cmd to create an exe file and also you can add icon using -i(I think so).
Visit this to learn about it from realpython which I love to read about python tutorials : https://realpython.com/pyinstaller-python/
By the way you can use python 3.8.6 or 3.9 which is the updated version of python 3.7.
Make sure your device is up to date, that could be the problem, also pyinstaller is a better, more modern alternative
I wrote a simple application which uses selenium to nagivate through pages and download their source code. Now I would like to make my application Windows-executable.
My setup.py file:
from distutils.core import setup
import py2exe, sys, os
sys.argv.append('py2exe')
setup(
options = {'py2exe': {'bundle_files': 1,
"dll_excludes": ['w9xpopen.exe', 'MSVCP90.dll', 'mswsock.dll', 'powrprof.dll', 'MPR.dll', 'MSVCR100.dll', 'mfc90.dll'],
'compressed': True,"includes":["selenium"],
}
},
windows = [{'script': "main.py", "icon_resources": [(1, "hacker.ico")]}],
zipfile = None
)
My program (main.py) (with setup.py file) is located in C:\Documents and Settings\student\Desktop. Py2exe builds my exe in C:\Documents and Settings\student\Desktop\dist.
I copied both webdriver.xpi and webdriver_prefs.json files to C:\Documents and Settings\student\Desktop\dist\selenium\webdriver\firefox\, but I'm getting the error when trying to launch my application:
Traceback (most recent call last):
File "main.py", line 73, in <module>
File "main.py", line 58, in check_file
File "main.py", line 25, in try_to_log_in
File "selenium\webdriver\firefox\webdriver.pyo", line 47, in __init__
File "selenium\webdriver\firefox\firefox_profile.pyo", line 63, in __init__
IOError: [Errno 2] No such file or directory: 'C:\\Documents and Settings\\student\\Desktop\\dist\\main.exe\\selenium\\webdriver\\firefox\\webdriver_prefs.json'
How to solve this?
Actually, it worked with such setup.py file:
from distutils.core import setup
import py2exe, sys, os
sys.argv.append('py2exe')
wd_path = 'C:\\Python27\\Lib\\site-packages\\selenium\\webdriver'
required_data_files = [('selenium/webdriver/firefox',
['{}\\firefox\\webdriver.xpi'.format(wd_path), '{}\\firefox\\webdriver_prefs.json'.format(wd_path)])]
setup(
windows = [{'script': "main.py", "icon_resources": [(1, "hacker.ico")]}],
data_files = required_data_files,
options = {
"py2exe":{
"skip_archive": True,
}
}
)
But the problem is I need to build SINGLE executable.
Have you tried to have a look at this answer for the "bundle_files = 1" problems? It helped me solving that specific problem.
TL;DR --Please check out this tool I built: https://github.com/douglasmccormickjr/PyInstaller-Assistance-Tools--PAT
Might I suggest using PyInstaller instead of py2exe or anything else for that matter since PyInstaller does a far better job in terms of bundling a single executable. I'm on Windows about 90% of the time (no complaints here) with my python coding-- PyInstaller is a way better option than py2exe (for me at least -- I've used/test a great deal of Windows compilers in the past with varied success). Maybe other people suffering from compiling issues could benefit from this method as well.
PyInstaller Prerequisites:
Install PyInstaller from: http://www.pyinstaller.org/
After PyInstaller installation-- confirm both "pyi-makespec.exe" and "pyi-build.exe" are in the "C:\Python##\Scripts" directory on your machine
Download my PyInstaller-Assitance-Tools--PAT (it's just 2 batch files and 1 executable with the executable's source python file too -- for the paranoid)...The file are listed above:
Create_Single_Executable_with_NO_CONSOLE.bat
Create_Single_Executable_with_CONSOLE.bat
pyi-fixspec.exe
pyi-fixpec.py (optional -- this is the source file for the executable -- not needed)
Place the exectuable file called "pyi-fixspec.exe" inside the previous "Scripts" folder I mentioned above...this makes compiling much easier in the long run!
let's get it working now...some slight code changes to your python application
I use a standard function that references the location of applications/scripts that my python application needs to utilize to work while being executed/operated. This function operates both when the app is a standalone python script or when it's fully compiled via pyinstaller.
Here's the piece of code I use...
def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
and here's my app using it....
source = resource_path("data\my_archive_file.zip")
that means the app/files look something like this in terms of directory structure:
C:\Path\To\Application\myscript_001.py <--- main application/script intended to be compiled
...
C:\Path\To\Application\data\my_archive_file.zip <---|
C:\Path\To\Application\data\images\my_picture.jpg <---| supporting files in the bundled app
C:\Path\To\Application\info\other_stuff.json <---|
...
Please note that the data/files/folders I'm bundling for my app are below the main executable/script that I'll be compiling...the "_MEIPASS" part in the function lets pyinstaller know that it's working as a compiled application...VERY IMPORTANT NOTE: Please use the function "resource_path" since the "pyi-fixspec.exe" application will be looking for that phrase/function while parsing/correcting the python application pathing
Goto the directory containing the 2 batch files mentioned above and type in either:
Option #1
C:\MyComputer\Downloads\PAT> Create_Single_Executable_with_NO_CONSOLE.bat C:\Path\to\the\python\file.py
The output executable file results in a GUI app when double clicked
Option #2
C:\MyComputer\Downloads\PAT> Create_Single_Executable_with_CONSOLE.bat C:\Path\to\the\python\file.py
The output executable file results in a WINDOWS CONSOLE app when double clicked -- expects commandline activity ONLY
Your new single-file-executable is done! Check for it in this location
C:\Original\Directory\ApplicationDistribution64bit\NameOfPythonFile\dist
If you do edit/change the original python file that has just been previously compiled, please delete the folder/contents of **\NameOfPythonFile** prior to next compile kickoff (you'll want to delete the historical/artifact files)
Coffee break -- or if you wany to edit/add ICONS to the executable (and other items too), please look at the generated ".spec" file and PyInstaller documentation for configuration details. You'll just need to kick off this again in the windows console:
pyi-build.exe C:\path\to\the\pythonfile.spec
You can build a single executable, which will run natively, by using Nuitka. It converts the Python code into C++ and then compiles it.
http://nuitka.net/
It does, however, require that you have a compiler installed. The appropriate versions of either Microsoft Visual C++ or GCC. Microsoft released "Microsoft Visual C++ Compiler for Python 2.7", which can be obtained here at https://www.microsoft.com/en-us/download/details.aspx?id=44266.
A nice installer of MinGW GCC for windows can be found at https://github.com/develersrl/gccwinbinaries with detailed instructions, including which MSVCRTXX.dll version to link with for which version of Python.
Things you will gain from this method of executable generation:
Doing this generates machine code, so it will be more difficult, but not impossible, to reverse engineer. Simply using Py2exe or PyInstaller, which are great for their intended use, only packages the byte compiled Python code, which is easily decompiled (http://www.simonroses.com/2013/10/appsec-myths-about-obfuscation-and-reversing-python/), into a zip appended executable.
Your application will also gain a bit of a speed boost. I wrote a blog post about this kind of thing at (I DO NOT receive money from click throughs or ads).
https://jaredfields83.wordpress.com/2015/12/21/squeezing-more-juice-from-python/.
The problem you have is that selenium is trying to open a file in a way that is not directly compatible with py2exe.
As you can see at line 63 here, selenium must open a preferences file that is usually shipped with the package. It uses the __file__ variable to find it, which doesn't play well with py2exe. As you have found, it is possible to work around that by also packaging up the prefs file in your distribution. However, that is now more than one file.
The py2exe wiki then has a recipe to use NSIS that will build a self-extracting executable of your complete distribution.
I am building a simple python app (myFile.py), using Python 3.4 with Selenium v2.44 (firefox web driver) and PyQt4 and want to distribute it. However, I am running into some problems including the webdriver.xpi and webdriver_prefs.json into the library.zip in my dist file.
Searching has given me plenty of results of people with the same problem, however, none of the proposed solutions seem to work for me.
My current setup.py:
from distutils.core import setup
import py2exe
wd_path = 'C:\\Python34\\Lib\\site-packages\\selenium\\webdriver'
required_data_files = [('selenium/webdriver/firefox',
['%s\\firefox\\webdriver.xpi'%wd_path, '%s\\firefox\\webdriver_prefs.json'%wd_path])]
setup(
windows= {"myFile.py"},
data_files = required_data_files,
options = {
"py2exe":{
"skip_archive": True,
"unbuffered": True,
"includes":["sip", "PyQt4"],
'optimize': 2
}
},
requires=['selenium'],
)
However, when the dist is created, I still have a library.zip that I can't manually add webdriver.xpi and webdriver_prefs.json too, additionally, it just creates a directory called selenium in the dist folder, it does not add it to the library. I was under the impression the -skip_archive option would NOT create a .zip file, but one is being created regardless.
Thanks in advance for your help,
Ryan
I have a project in Python 3.4 and GTK+ 3. I'm on Windows XP SP3 32-bit (VirtualBox).
I need to compile down to an executable using py2exe. (Do NOT suggest cx_freeze. It has ten times the problems on this project than py2exe).
My setup.py is as follows.
#!/usr/bin/python
from setuptools import setup
import py2exe
setup(name="Redstring",
version="2.0",
description="REDundant STRING generator",
author="MousePaw Labs",
url="http://www.mousepawgames.com/",
maintainer_email="info#mousepawgames.com",
data_files=[("", ["redstring.png", "redstring_interface.glade"])],
py_modules=["redstring"],
windows=[{'script':'redstring.py'}],
options={"py2exe":{
"unbuffered": True,
"compressed":True,
"bundle_files": 1,
'packages':['gi.repository'],
}},
zipfile=None
)
When I run it via C:\Documents and Settings\Jason\Desktop\redstring2>python setup.py py2exe, I get the following output (in full).
running py2exe
running build_py
1 missing Modules
------------------
? gi.repository.Gtk imported from __SCRIPT__
Building 'dist\redstring.exe'.
C:\Documents and Settings\Jason\Desktop\redstring2>
The actual script, redstring.py, runs without a hitch in my Windows environment. In that, I have the following (working) line of code: from gi.repository import Gtk That is ALL I import from gi.repository in the entire project.
If I swap the line in setup.py to 'packages':['gi'],, the error output switches to about 24-some-odd missing modules, all of them belonging to gi.repository. If I try and import "Gtk" or "gi.repository.Gtk" in either 'packages': or 'includes':, I get an error that the file in question being imported cannot be found.
I spent eight hours on #python (IRC channel) today, and no one could solve this. I need this packaged down to a Windows binary this week.
NOTE: This question is not a duplicate; while it is a similar issue, it is a) not the same error message, and b) neither answer solves the question in any way.
I solved this by, first of all, downgrading to Python 2.7. (GTK+ 3.8 is still fine.) py2exe apparently has known issues with Python 3.
Second, I switched...
options={"py2exe": {
"bundle_files": 1,
}
to
options={"py2exe": {
"bundle_files": 3,
}
For some reason, py2exe cannot include certain files needed to run the gi library when 'bundle_files' is set to 1 or 2.
The full setup.py that works with py2exe for my project can be found on GitHub. I run it on cmd with python setup.py py2exe.
i'm writing an installer using py2exe which needs to run in admin to have permission to perform various file operations. i've modified some sample code from the user_access_controls directory that comes with py2exe to create the setup file. creating/running the generated exe works fine when i run it on my own computer. however, when i try to run the exe on a computer that doesn't have python installed, i get an error saying that the import modules (shutil and os in this case) do not exist. it was my impression that py2exe automatically wraps all the file dependencies into the exe but i guess that this is not the case. py2exe does generate a zip file called library that contains all the python modules but apparently they are not used by the generated exe. basically my question is how do i get the imports to be included in the exe generated by py2exe. perhaps modification need to be made to my setup.py file - the code for this is as follows:
from distutils.core import setup
import py2exe
# The targets to build
# create a target that says nothing about UAC - On Python 2.6+, this
# should be identical to "asInvoker" below. However, for 2.5 and
# earlier it will force the app into compatibility mode (as no
# manifest will exist at all in the target.)
t1 = dict(script="findpath.py",
dest_base="findpath",
uac_info="requireAdministrator")
console = [t1]
# hack to make windows copies of them all too, but
# with '_w' on the tail of the executable.
windows = [{'script': "findpath.py",
'uac_info': "requireAdministrator",
},]
setup(
version = "0.5.0",
description = "py2exe user-access-control",
name = "py2exe samples",
# targets to build
windows = windows,
console = console,
)
Try to set options={'py2exe': {'bundle_files': 1}}, and zipfile = None in setup section. Python will make single .exe file without dependencies. Example:
from distutils.core import setup
import py2exe
setup(
console=['watt.py'],
options={'py2exe': {'bundle_files': 1}},
zipfile = None
)
I rewrite your setup script for you. This will work
from distutils.core import setup
import py2exe
# The targets to build
# create a target that says nothing about UAC - On Python 2.6+, this
# should be identical to "asInvoker" below. However, for 2.5 and
# earlier it will force the app into compatibility mode (as no
# manifest will exist at all in the target.)
t1 = dict(script="findpath.py",
dest_base="findpath",
uac_info="requireAdministrator")
console = [t1]
# hack to make windows copies of them all too, but
# with '_w' on the tail of the executable.
windows = [{'script': "findpath.py",
'uac_info': "requireAdministrator",
},]
setup(
version = "0.5.0",
description = "py2exe user-access-control",
name = "py2exe samples",
# targets to build
windows = windows,
console = console,
#the options is what you fail to include it will instruct py2exe to include these modules explicitly
options={"py2exe":
{"includes": ["sip","os","shutil"]}
}
)