Using Esky to Freeze/Package a Cocoa PyObjC Python Application - python

So I'm trying to put together an auto-update functionality for my standalone OSX Python application, that's built on PyObjC. It works great simply packaging it via py2app, but I'm attemping to freeze it with Esky as part of an effort to implement the update feature.
As far as I can tell it's my setup.py formatting for Esky. I'm not sure exactly how to tell Esky to pass on the name of my .Xib file to py2app. Here's what my direct py2app setup.py looks like, successfully including the required .Xib file for the GUI:
setup.py for Py2app
from setuptools import setup
APP = ['MyApp.py']
DATA_FILES = ['MyApp.xib']
OPTIONS = {'argv_emulation': False, 'packages' : ['PIL']}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
iconfile="MyApp.icns"
)
Looking around at other people's posts, it looks like you can pass settings to py2app via the slightly differently structured Esky setup.py, but I can't for the life of me figure out the exact structure of the arguments to pass the .Xib file to py2app, from Esky.
setup.py for Esky
from esky import bdist_esky
from distutils.core import setup
setup(name="MyApp",
version="1.3.3",
iconfile="MyApp.icns",
data_files=['MyApp.xib'],
scripts=["MyApp.py","midheaven.py"],
options={"bdist_esky":{
"includes":["PIL"],
"excludes":['pydoc'],
"freezer_module": "py2app",
"freezer_options": {
"plist": {
'argv_emulation': False,
'packages': ['PIL'],
},
"data_files": ['MyApp.xib'],
},
},
},
)
Everything packages without an error, but of course if I try to run the Esky freeze of the app it crashes right away. I'm positive it's because it's not attaching the .Xib GUI properly. Anyone have experience with this, or ideas on how this should actually be formatted? Would absolutely love to figure this out and have it up on here for posterity.

You are correct esky does something different than what you might expect. Looking in the demo/tutorial folder is what got me on the right path.
setup(name="MyApp",
data_files=[('', ['MyApp.xib']),
('files', ['file1', 'file2']),
('img', glob(r'.\img\*.*'))
]
...
So you have a whole bunch of tuples, where the first entry is the path in your package to include the files and the second is an iterable of files to put there
You can remove the second instance of data_files that you have in the options dict.
Update
Try
from esky.bdist_esky import Executable
executables = [Executable('example_gui.py', icon='myico.ico', gui_only=True,)]
setup(
scripts = executables
...

Related

What is the proper way to turn a python app into a standalone app with py2app?

I have built a simple python app with Tkinker, which has a super small sqlite file with it. The app is here, https://github.com/yts61/bookstore_app.git
Having failed in pyinstaller many times, i am turing to py2app in the hope to make one standalone app file which i can share around. I googled and followed this youtube tutorial,
https://www.youtube.com/watch?v=u4ykDbciXa8, and again failed the mission. My setup.py file is like the one below,
from setuptools import setup
APP = ['frontend.py']
DATA_FILES = ['books.db','backend.py']
OPTIONS = {
'iconfile':'favicon.ico',
'argv_emulation': True,
'packages': ['certifi'],
}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
In the terminal, i tried python setup.py py2app -A, and clicked the frontend file in Content/MacOS/frontend to test run the app as suggested by the tutorial, however, the app won't run, and my Mac flashed and reset itself.
Would anyone please help ?
I have asked another question about building this standalone app with pyinstaller.
What is the proper way to use pyinstaller on Mac?

How to modify py2app setup.py to allow import of my own modules?

I'm creating an app on my Mac (Catalina 10.15.4, system python 3.7) using py2app with python 3.7 and the IDLE IDE. The app is called network_plotter.py and calls functions in another file, network_tools.py. Currently both files reside in the same directory,
Including the line import network_tools at the start of network_plotter.py allows me to run the file network_plotter.py in IDLE with no problems.
Now to create the network_plotter app Following the py2app documentation instructions, I created my setup file, which looks like the following:
from setuptools import setup
APP = ['network_plotter.py']
DATA_FILES = []
OPTIONS = {}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
)
I need for the network_tools.py script to be included in the final app distribution, and I'm not sure what to modify above to do so. I've tried inserting after app=APP, each of the following lines, none of which works:
py_modules=['/Users/fishbacp/Desktop/network_tools']
ext_modules=['/Users/fishbacp/Desktop/network_tools.py']
scripts=['/Users/fishbacp/Desktop/network_tools.py']
In each case, the final app will not run, either when I double-click on it or try running it from the terminal. The latter approach leads to the error message, "No module named 'pygments.lexers.python"

py2exe can't find module if in different path

I'm trying to create an exe using the following config options -
setup(name='tidalZabbix',
version=version,
description='python module to submit job stats to Zabbix',
url='',
author='Me',
author_email='me#company.com',
license='',
# folders with functions
console=[{'script': os.path.join(BASE_DIR, 'code/tidal_zabbix.py')}],
options={
'build': {'build_base': 'c:/tidalZabbix/build'},
'py2exe':
{
'dist_dir': 'c:/tidalZabbix',
'includes': ['decimal'],
}
}
)
I have a separate module in the code directory called code/ZabbixSender.py
when I try to run python setup.py py2exe I get the following error -
The following modules appear to be missing
['ZabbixSender']
If I move the ZabbixSender.py to the same location as my setup.py the build works fine.
ie. if I do this:
'includes': ['decimal', 'code.ZabbixSender'],
or
'includes': ['decimal', 'ZabbixSender'],
It still doesn't find the Module.
I'd like to think this is bad error reporting by p2exe.
The solution has nothing to do with my py2exe config but in the tidal_zabbix.py script being called.
This was the "incorrect" import
from ZabbixSender import ZabbixPacket, ZabbixSender
As soon as I modified it to this -
from code.ZabbixSender import ZabbixPacket, ZabbixSender
The build worked with no issues. Odd though considering running directly from python had no issues with the code.

Packaging Selenium in py2exe

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

Make exe file from python selenium tests

I try to build my python selenium tests in exe file and run it on many machines for keeping tests independent of the environment. But result *.exe file can't find selenium webdriver. How can I include all selenium dependencies in *.exe file? Or maybe is there some another way for it?
Is it possible to make virtual environment and distribute it?
I am assuming you are using py2exe for generating exe. You will need to specify the location of selenium webdriver in the setup.py file.
Following code should help:
from distutils.core import setup
import py2exe
# Change the path in the following line for webdriver.xpi
data_files = [('selenium/webdriver/firefox', ['D:/Python27/Lib/site-packages/selenium/webdriver/firefox/webdriver.xpi'])]
setup(
name='General name of app',
version='1.0',
description='General description of app',
author='author name',
author_email='author email',
url='',
windows=[{'script': 'abc.py'}], # the main py file
data_files=data_files,
options={
'py2exe':
{
'skip_archive': True,
'optimize': 2,
}
}
)
Like most other binary, it's probably required to include the DLL or whatever library you need, with the binary file. For example:
C:\tests\
run_tests.exe -- this will read from webdriver.dll
selenium-webdriver.dll
Also, from my .NET days i know that you were able to actually embed the library straight into the EXE, which makes it rather large.
You may try pyinstaller,it is simple to install and simple to use.
Install:
pip install pyinstaller
To exe:
pyinstaller yourprogram.py
This is old but I was looking for the same thing and I did have to dig in many different websites to find out my problem, so hopefully this will help others.
I was using py2exe to build my exe file but it didn't work so I decided trying pyinstaller and yeah, it worked.
Just gonna put the things in items to be more organized:
Py2exe:
I first started with py2exe and I was getting error like this:
python setup.py py2exe Invalid Syntax (asyncsupport.py, line 22)
I could fix it by deleting some of the things in the setup file, it looked like this in the end.
data_files = [('selenium/webdriver/chrome', ['C:\Python27\Lib\site-packages\selenium\webdriver\chrome\webdriver.py'])]
setup(
name='General name of app',
version='1.0',
description='General description of app',
author='author name',
author_email='author email',
url='',
windows=[{'script': 'final_headless.py'}], # the main py file
data_files=data_files,
options={
'py2exe':
{
'skip_archive': True,
'optimize': 2,
'excludes': 'jinja2.asyncsupport',
'dll_excludes': ["MSVCP90.dll","HID.DLL", "w9xpopen.exe"]
}
}
)
It could run the py2exe but the exe file didn't work, then I moved to pyinstaller.
Pyinstaller:
For me pyinstaller look way easier than py2exe, so I am keeping with this from now. We only "problem" was that without the webdriver in the path the exe doesn't run.
But as soon as you have it in your variables path you are good to go.
Conclusion, using pyinstaller was my solution + adding webdriver to path.

Categories