Making a standalone .exe file of a python script - python

I have a python script which contains:
tempBook = temp.Workbooks.Open("c:\users\CNAME\desktop\Template.xlsx")
Everything works fine but when I create a .exe of my script the Template.xlsx is not included in its 'build' folder, it needs Template.xlsx to be present on the desktop. I want to make a portable exe.
Is there any way so that it can be included in the build, and make a standalone exe without any dependencies?

You need to move the file to your package, and list it in your setup.py:
setup(
# ...
data_files = [('', ['Tempate.xlsx',])],
)
See the data_files documentation for py2exe, which includes a utility function for automating adding data files.
The files will be added in your app root. From your main script, you can determine your app root by using:
import os
try:
approot = os.path.dirname(os.path.abspath(__file__))
except NameError: # We are the main py2exe script, not a module
import sys
approot = os.path.dirname(os.path.abspath(sys.argv[0]))

Related

No such file or directory:'main.ui' in cx_freeze

I used PyQT5 to develop a software using python.
now i have main.ui and main.py
i've used this command line to read main.ui file:
FORM_CLASS,_=loadUiType(path.join(path.dirname(__file__),"main.ui"))
now my main.ui is connected to my main.py file where main python code is written.
I also created setup.py as per cx_freeze instruction
Then I've used cmd command:
python setup.py build_exe
once completed i have received below error:
No such file or directory:'main.ui'
so ho i can solve this issue?
If you are going to use external resources then you should use the cx_freeze manual for data files:
Using data files Applications often need data files besides the code,
such as icons. Using a setup script, you can list data files or
directories in the include_files option to build_exe. They’ll be
copied to the build directory alongside the executable. Then to find
them, use code like this:
def find_data_file(filename):
if getattr(sys, 'frozen', False):
# The application is frozen
datadir = os.path.dirname(sys.executable)
else:
# The application is not frozen
# Change this bit to match where you store your data files:
datadir = os.path.dirname(__file__)
return os.path.join(datadir, filename)
An alternative is to embed data in code, for example by using Qt’s
resource system.
So in your case modify your code to:
import os.path
import sys
# ...
def find_data_file(filename):
if getattr(sys, 'frozen', False):
# The application is frozen
datadir = os.path.dirname(sys.executable)
else:
# The application is not frozen
# Change this bit to match where you store your data files:
datadir = os.path.dirname(__file__)
return os.path.join(datadir, filename)
# ...
FORM_CLASS,_=loadUiType(find_data_file("main.ui"))
# ...
And change the setup.py to include the .ui:
from cx_Freeze import setup, Executable
setup(
name="mytest",
version="0.1",
description="",
options={"build_exe": {"include_files": "main.ui"}},
executables=[Executable("main.py")],
)

Compiling python project with Cx-Freeze

I'm trying to make and executable from a project I'm working on, to test it on a different computer, without requiring python installed.
I want to use cx freeze to build and exe file, and this is my project tree:
- Project
- objects
blocks.py
enemy.py
item.py
player.py
__init__.py
- scripts
camera.py
chunk_manager.py
__init__.py
- textures
- items
- player
- terrain
- UI
- void
index.py
__init__.py
main.py
settings.py
setup.py
map.json
As you can probably tell, this is a game.
Anyways, what I have done is executing just cxfreeze main.py --target-dir=./ dist and it generated a build directory with a lot of stuff in it.
It generated a linux executable, but thats fine, I want to test if I can make it python-independent first, and I'll solve the .exe part later.
So, I executed the file, and nothing happened. Then I tried running from the terminal and it said that it was missing the camera.py file. I went into the generated directory and I found out that cxfreeze had not copied that file. I tried moving in in there myself, but it did not work.
I started checking for other files, and I found out that only the textures had been copied.
I thought this was just because of the one line command I used, so I am now trying to make a setup.py file (as you can see in the file tree) but I am lost in how to import my custom packages (objects, scripts, and textures) and the files in the same directory as main.py
This is how my setup.py file looks like:
import sys
from cx_Freeze import setup, Executable
options = {
'build_exe': {
'includes': ['camera', 'chunk_manager'], 'path': sys.path + ['scripts']
}
}
setup(
name = "Void Boats",
version = "alpha0.1",
options = options,
executables = [Executable("main.py")])
I am not sure how would I put all the packages in the 'include' section, and I can't find anything on the internet that uses more than a simple file like helloworld.py, and the samples of cxfreeze on their github only show how to import files from one directory. Do I have to move everything into one single package and put all the files in the same 'include'? Or can I have one include for each package I have? Any help would be pretty much appreciated.
Edit: I'm running on ParrotSec 4.9 (Debian based)
Use "python -m setup.py build" on cmd, that will build exe.
Example setup with extra folders:
from cx_Freeze import setup, Executable
import sys
version = "0.0.6"
build_options = {
"packages": [],
"excludes": [],
"build_exe": "X:\\builds\\",
"include_files": ["Sequence_Sample/", "icons/"],
}
base = "Win32GUI" if sys.platform == "win32" else None
executables = [Executable("MainUIController.py", base=base, targetName="pym")]
setup(
name="Python Image Macro Project",
version=version,
description="Image Based macro project.",
options={"build_exe": build_options},
executables=executables,
)
Python 3.8 and later has problem with cx_freeze 6.1 - not copying python dll.
cx_freeze 6.2 is strongly recommended if that's the case.
You'll have to clone cx_freeze and build it, then install it to use 6.2.

Module import precedence in Pyinstaller program

I am trying to have an easy way to update a program I am working on, by being able to just place replacement .py files in a folder which I then put at the top of the sys.path list so all import statements will first check that folder and not my top level directory, importing the newer .py files and not the ones used to build the program originally with PyInstaller. Right now, if I use this code:
import sys,os
bundlePath = 'c:/tests/importTest'
print ("Bundle path: {}".format(bundlePath))
importPath = bundlePath + '/uploads'
sys.path.insert(0,importPath)
print ("Import path: {}".format(sys.path[0]))
os.chdir(sys.path[0])
import testyTastery
print(testyTastery.message)
My Python IDE or running this script through the command line will print the message from uploads/testyTastery.py (there is also a testyTastery.py in the top level directory). However, when I change line 2 to bundlePath = sys.path[1] (because builds in PyInstaller put the top level directory in sys.path[1], at least in Windows, sys.path[0] points to a base_library.zip that PyInstaller creates) and build this into a folder bundle for PyInstaller (making sure to either copy uploads/testyTastery.py or include it in the .spec file), I get the message from the testyTastery.py script, not the uploads/testyTastery.py script.
Any idea on how to easily change this? To be clear, the first two print statements result in the same output for both running it before and after compiling with PyInstaller, after changing the second line as mentioned.
I don't know, but maybe it has something to do with PyInstaller always looking at files it packages before looking in sys.path for imports?
Edit: To be clear, if I do a build with none of the files available, then put the files in the appropriate folders afterward, the import precedence is just like in the command line / IDE. This suggests to me that files packaged by PyInstaller are higher up in the import hierarchy.
I finally found a solution to this problem. To be clear, the original problem was to package up files (in folder option) with PyInstaller, and later just drop in files to replace the ones that were originally packed up. Because PyInstaller inserts its method of loading files into sys.meta_path, you need to install your own custom import method before PyInstaller's. Here is what I've got (changing the order of system path is because PyInstaller also changes sys.path[0] to a zip file, sys.path[1] is what you really want to be at the top of the sys.path chain if you are doing this or using sys.path[0] in your program:
import os
import sys
sys.path = [sys.path[1]] + [sys.path[0]] + sys.path[2:]
from importlib.machinery import SourceFileLoader
class MyImporter(object):
def find_module(self, module_name, package_path):
print ('entered again')
if os.path.exists("{}/{}.py".format(sys.path[0],module_name)):
return SourceFileLoader(module_name,"{}/{}.py".format(sys.path[0],module_name))
else:
return None
def load_module(self, module_name):
if os.path.exists("{}/{}.py".format(sys.path[0],module_name)):
return SourceFileLoader(module_name,"{}/{}.py".format(sys.path[0],module_name)).load_module()
else:
return None
sys.meta_path.insert(1,MyImporter())
If you do this in your main file that PyInstaller imports then your entire program will search sys.path[0] (It would be trivial to add more folders to your system path and search them as well, of course) before searching for PyInstaller packaged modules.

setup.py not create proper folders/configuration in mac osx?

I am trying to create the setup.py for a script. The setup.py looks like this:
from setuptools import setup
setup(name='readfile',
version='1.0',
description='A flexible module to read ascii files',
author='author',
author_email='author#gmail.com',
url='',
modules=['readfile'])
the script is called readfile.py and doesn't have any additional files or scripts. All I want to do is have setup.py put it on the correct location automatically. So I do
python setup.py install
This creates a folder
/Library/Python/2.7/site-packages/readfile-1.0-py2.7.egg
However, it doesn't update the python path nor create a directory called readfile in site-packages directly, so I cannot import the module. Am I missing an option that would do any of these?
Thanks!
EDIT:
I had some more trouble afterwards; with various combinations of setup() arguments I was able to import readfile but none of its modules. In the end, the setup.py was fine and I just needed the __init__.py, without the extra folder. So the three files (readfile.py, setup.py, __init__py) are in the same folder now and everything works as it should.
Do you have a folder at the same level as setup.py called readfile?
Inside that, is there a file called __init__.py?
Inside that folder is there also your source file called readfile.py?
That seems to work for me.
The .egg file that you reference is just a zip file that contains everything you need. There should be no need to update python path or create the readfile directory. Those things are not needed to import readfile.

Python - running script is in an egg?

i created an executable egg to make it as an single file executable.
setup.py:
#!/usr/bin/env python
from setuptools import setup, find_packages
setup(
name='app',
version='0.5',
description='foo',
author='microo8',
author_email='xxx#email.com',
packages=["foo", "bar"],
install_requires=["sqlalchemy>=0.7", "paramiko>=1.7.7.1"],
entry_points = {
'setuptools.installation': [
'eggsecutable = foo.module:main',
]
}
)
I can now call it: ./app-0.5-py2.7.egg, but the relative paths are all in the egg.
when I call print __file__ in the main function it prints /home/user/app-0.5-py2.7.egg/foo/module.py. I want to read an config file that must be in the same dir as the egg. And the same script must be executable also as "non-egg", so the config file will be in the dir with the script.
how can i find out that the script is executed from an egg and also the egg path?
So I dont know how to check that the running script is in an egg, but the config file path can be obtained with this: os.path.realpath('config.cfg').
This suits me and when I have a dir with the executable egg and an config file this is a correct path.
Also when I have just the script in the dir with the config file it also is correct.
And also when i use pyinstaller to create an singlefile exe.
You should load your configuration file using the ResourceManager API. That way your eggified code can load the configuration file even when zipped.
import pkg_resources
configdata = pkg_resources.resource_string(__name__, "myconfigfile.cfg")
The API can check for existence, test for directories, read data or provide you with an open file object for any resource that is part of your egg.
The API takes care of all the details; it'll extract files to a temporary directory for example, if you absolutely must have a filename for a resource but are running from a zipped egg.
Most of all, it'll work regardless of whether or not you are in fact installed as an egg or stand-alone.

Categories