Create .app / .dmg with Esky - macos

I'm developing a GUI app in Python. I use cx_Freeze to turn my app into .app/ / .dmg files for OS X users. So, for instance I can use python setup.py bdist_dmg to make cx_Freeze create a .dmg file that my users can use to install my app.
I now want my app to update itself automatically. Esky seems to be a promising framework for doing this. I can do python setup.py bdist_esky to create a version of my app that updates itself. It produces the following directory structure:
myapp
myapp-0.1/
myapp
...
...
The top-level myapp is Esky's bootstrapping executable. It looks in the current directory, finds myapp-0.1/ as the latest version and then launches myapp-0.1/myapp.
How do I package this into a .dmg file which I can ship to my users? After my modifications to setup.py to get bdist_esky to work, bdist_dmg no longer works. The impression I get is that Esky is simply not meant to be used with bdist_dmg. Its documentation doesn't mention DMG files at all and I also couldn't find anything on Google.
As a first step, I tried to manually turn the files generated by Esky into an OS X .app/ bundle:
myapp.app/
Contents/
Info.plist
MacOS/
myapp
myapp-0.1/
myapp
...
...
Info.plist contains the minimum amount of necessary information to get OS X to run myapp. When I try to run myapp.app however, I get:
Traceback (most recent call last):
File "<string>", line 318, in bootstrap
File "<string>", line 442, in get_best_version
FileNotFoundError: [Errno 2] No such file or directory: '/Users/michael/Temp/myapp.app/appdata'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<string>", line 689, in <module>
File "<string>", line 335, in bootstrap
RuntimeError: no usable frozen versions were found
Looking at Esky's source code, it appears to have some special handling for OS X bundles in its appdir_from_executable(...) function. To make Esky happy, I tried to rearrange my files so appdata/ actually exists:
myapp.app/
appdata/
myapp-0.1/
myapp
...
Contents/
Info.plist
MacOS/
myapp
...
Unfortunately, this results in another error:
Traceback (most recent call last):
File "<string>", line 689, in <module>
File "<string>", line 336, in bootstrap
File "<string>", line 363, in chainload
File "<string>", line 425, in _chainload
UnboundLocalError: local variable 'exc_value' referenced before assignment
Is this really that difficult? Am I the only one who wants to use Esky and ship files to users in the (standard) .dmg format? What am I missing?

Michael, I saw your comment in the github issue as well. Let me answer it here.
I had the same requirement and resolved in a similar way but I think I didn't use cx_Freeze. Another difference could be that I used Python 2.7.x. The best way to help you is to show you a few relevant files which worked well for me for creating .app and .dmg.
1) The main setup file of the python project:
https://dl.dropboxusercontent.com/u/13110611/temp/package_esky/setup_esky.py
2) The utility script I used to prepare some data files etc
https://dl.dropboxusercontent.com/u/13110611/temp/package_esky/prepare_setup.py
3) The main shell script I used to create app and DMG. That is, this script will call everything else, and it's the only script I used from command line directly.
https://dl.dropboxusercontent.com/u/13110611/temp/package_esky/package.sh
4) The dmg-setup script which will create DMS from .app file. It's just a simple wrapper script to call create-dmg, an open souce project.
https://dl.dropboxusercontent.com/u/13110611/temp/package_esky/dmg-setup
Please try and let me know in case you have any other questions or issues.

Related

Pyinstaller error on mac: Package not found

My program is supposed to open a docx file 'Core.docx' with python-docx and does it just fine until I make an executable out of it with pyinstaller. I got the same error doing this on Windows 10 but was able to fix it by manually copying 'Core.docx' into the dist folder. On Mac, it doesn't solve it.
Error:
Traceback (most recent call last):
File "script.py", line 13, in <module>
File "docx/api.py", line 25, in Document
File "docx/opc/package.py", line 128, in open
File "docx/opc/pkgreader.py", line 32, in from_file
File "docx/opc/phys_pkg.py", line 30, in __new__
docx.opc.exceptions.PackageNotFoundError: Package not found at 'Core.docx'
[7946] Failed to execute script 'script' due to unhandled exception!
I've also tried the function --add-data after reading this exchange:
pyinstaller -F --add-data "Core.docx:Core.docx" script.py
It ran but nothing seems to have actually changed.
Does anyone know of any solutions?

PyInstaller win32ctypes.pywin32.pywintypes.error: (2, 'LoadLibraryExW', 'The system cannot find the file specified.')

While using PyInstaller (dev version 4.0.dev0+8196c57ab), produced an OSError: [WinError 2] 'The system cannot find the file specified.'
Python version: 3.7
GUI: PySide2 5.13.0
Other packages: lxml, BeautifulSoup, Matplotlib (with dependencies like numpy), Pandas, pypiwin32, reportlab, Theano
Anaconda 3, Windows
Compiled with PyInstaller --onedir
What I've tried:
Tried downgrading PyInstaller to 2.1 as suggested here: https://github.com/pyinstaller/pyinstaller/issues/3916 but doesn't work as Python 3 is not supported
Was originally on PyInstaller 3.5, upgraded to dev version as suggested under some of the issues on PyInstaller github
Tried including --exclude-module=.git
import PyInstaller.__main__
if __name__ == '__main__':
PyInstaller.__main__.run([
'--name=%s' % 'Dummy App',
'--onedir',
'--nowindowed',
r'--workpath=C:\Users\User1\Desktop\build7',
r'--distpath=C:\Users\User1\Desktop\dist7',
'--hidden-import=theano.tensor.shared_randomstreams',
'--hidden-import=pandas._libs.tslibs.timedeltas',
'--clean',
'--add-data={0};.'.format('redacted.xml'),
'--add-data={0};{0}'.format('redacted_folder'),
'--add-data={0};.'.format('redacted.pdf'),
'--exclude-module={0}'.format('.git'),
'--log-level=WARN',
'MainWindow.py'
])
Full stacktrace:
79702 DEBUG: Analyzing .git\objects\78\e83411cea88cd038acb12c005a984fc0d6d423
Traceback (most recent call last):
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\win32ctypes\pywin32\pywintypes.py", line 35, in pywin32error
yield
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\win32ctypes\pywin32\win32api.py", line 43, in LoadLibraryEx
return _dll._LoadLibraryEx(fileName, 0, flags)
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\win32ctypes\core\ctypes\_util.py", line 42, in check_null
raise make_error(function, function_name)
OSError: [WinError 2] The system cannot find the file specified.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:/Users/User1/Dropbox/GitHub_Repos/DiabetesReportGenerator_v2/pyinstaller_freeze.py", line 37, in <module>
'MainWindow.py'
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\PyInstaller\__main__.py", line 112, in run
run_build(pyi_config, spec_file, **vars(args))
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\PyInstaller\__main__.py", line 63, in run_build
PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\PyInstaller\building\build_main.py", line 732, in main
build(specfile, kw.get('distpath'), kw.get('workpath'), kw.get('clean_build'))
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\PyInstaller\building\build_main.py", line 679, in build
exec(code, spec_namespace)
File "C:\Users\User1\Dropbox\GitHub_Repos\DiabetesReportGenerator_v2\Risk Calculator.spec", line 17, in <module>
noarchive=False)
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\PyInstaller\building\build_main.py", line 242, in __init__
self.__postinit__()
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\PyInstaller\building\datastruct.py", line 158, in __postinit__
self.assemble()
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\PyInstaller\building\build_main.py", line 468, in assemble
redirects=self.binding_redirects))
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\PyInstaller\depend\bindepend.py", line 226, in Dependencies
for ftocnm, fn in getAssemblyFiles(pth, manifest, redirects):
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\PyInstaller\depend\bindepend.py", line 402, in getAssemblyFiles
for assembly in getAssemblies(pth):
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\PyInstaller\depend\bindepend.py", line 353, in getAssemblies
res = GetManifestResources(pth)
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\PyInstaller\utils\win32\winmanifest.py", line 1005, in GetManifestResources
return winresource.GetResources(filename, [RT_MANIFEST], names, languages)
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\PyInstaller\utils\win32\winresource.py", line 168, in GetResources
hsrc = win32api.LoadLibraryEx(filename, 0, LOAD_LIBRARY_AS_DATAFILE)
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\win32ctypes\pywin32\win32api.py", line 43, in LoadLibraryEx
return _dll._LoadLibraryEx(fileName, 0, flags)
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\contextlib.py", line 130, in __exit__
self.gen.throw(type, value, traceback)
File "C:\Users\User1\Anaconda3\envs\ids_gui\lib\site-packages\win32ctypes\pywin32\pywintypes.py", line 37, in pywin32error
raise error(exception.winerror, exception.function, exception.strerror)
win32ctypes.pywin32.pywintypes.error: (2, 'LoadLibraryExW', 'The system cannot find the file specified.')
P.S. Compilation and the exe functioned perfectly with virtualenv environment created from Anaconda environment earlier (without need for --exclude-module=.git), but was too bloated with packages because the virtualenv environment is still considered to be part of the conda environment. So I used a new conda environment, and this error appeared
I've gotten it to work by creating another virtualenv environment in this new conda environment, but that is a very roundabout way. Is there any workaround?
For me, PyInstaller seems to search through .git folder and redacted_folder unnecessarily
I solved this problem by:
MOVING the folder(s) out of the directory before freezing
Additionally, if the folder is required for the frozen app to run (e.g. as a data folder), I would also either:
Comment / remove the corresponding part for --add-data and manually copy the folder over, or
Change the path for --add-data e.g. if you moved redacted_folder to your Desktop, you can change to '--add-data=C:/Users/User1/Desktop/redacted_folder'
You'll still need .git and redacted_folder back in the original directory to use Git and run your code without freezing
For example, I had trouble with .git and redacted_folder. The frozen executable needed redacted_folder to run parts of the code.
What I did was:
Move .git and redacted_folder to a separate directory
Then, I commented out the line to add data for redacted_folder:
import PyInstaller.__main__
if __name__ == '__main__':
PyInstaller.__main__.run([
'--name=%s' % 'Dummy App',
'--onedir',
'--nowindowed',
r'--workpath=C:\Users\User1\Desktop\build7',
r'--distpath=C:\Users\User1\Desktop\dist7',
'--hidden-import=theano.tensor.shared_randomstreams',
'--hidden-import=pandas._libs.tslibs.timedeltas',
'--clean',
'--add-data={0};.'.format('redacted.xml'),
# Remove `redacted_folder` and comment out the following line
# '--add-data={0};{0}'.format('redacted_folder'),
'--add-data={0};.'.format('redacted.pdf'),
'--exclude-module={0}'.format('.git'),
'--log-level=WARN',
'MainWindow.py'
])
After freezing, I copied redacted_folder over to the appropriate location relative to the frozen executable in distpath
This was fixed. Update PyInstaller.
I installed pyinstaller in a new conda environment using pip, however pywin32 did not get installed by default (eventhough documentation mentioned it would). Installing it fixed the error for me.
I had this same issue and found another thread where somebody uninstalled Python and then reinstalled Python to fix it.
The key information to understand the problem though, was that they had originally installed Python using Microsoft Store. When they reinstalled Python, they just downloaded Python from python.org and this took care of the problem. It worked for me too.
It seems very likely that something in the Microsoft Store version is causing problems like this.
Start from administrator cmd or ide and try again, it's helped me.
Running from Jupyter Notebook with elevated privilegies worked for me!

How to debug C code with lldb in macOS Mojave?

I was using gdb in Linux but now I have switched to Mac and read that lldb is the alternative to gdb in Apple devices. However, I'm getting an error when I try to use lldb (I also tried gdb but it does not recognize the files as executable). When I try to use it I get the following errors:
sanad#Sanads-MBP  ~/Desktop/cppLab  lldb ./a.out  ✔  623  01:43:54
(lldb) target create "./a.out"
Traceback (most recent call last):
File "", line 1, in
File "/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python/lldb/__init__.py", line 98, in
import six
ImportError: No module named six
Traceback (most recent call last):
File "", line 1, in
NameError: name 'run_one_line' is not defined
Traceback (most recent call last):
File "", line 1, in
NameError: name 'run_one_line' is not defined
…and a dozen more NameErrors exactly like this until the output ends with:
Current executable set to './a.out' (x86_64).
(lldb)
lldb links to the System Python.framework, and can only load other python modules if they were built along with that Python library. Turns out, the way Python works if you don't explicitly tell it where to find Python modules it will look alongside the "python" binary that it finds in your PATH. So if you've installed another python and have it in your PATH, then lldb's python will try to load Python modules that won't actually load properly. The current workaround is just to clear you hand-installed Python from your PATH environment variable in whatever Terminal window you want to run lldb from
This was recently fixed (r356819 on llvm.org) and will make it into the Xcode release in the near future.

Setting up OCR tool in python

I am a complete code novice. I am trying to teach myself python and so far I've been able to do rudimentary scripting. I want to try and learn how to use an OCR which might be somewhat advanced for me, but I'm doing it for fun so I have all the time in the world.
I'm trying to set up pytesser and I understand I need to download both the pytesser module and a PIL. I think there is a problem with how I'm storing my files.
Right now my PIL directory is located in:
C:\Python27\Lib\site-packages
and my pytesser_v0.01 directory is located in:C:\Python27\Lib\site-packages
I try to do the basic test found here
And I keep getting the following error
>>> from pytesser import*
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named pytesser
I think this is a very simple question because I keep looking to where to install my PIL and pytesser directories and every online forum/help starts by saying "install it" and not where.
Edit:
I found the correct place to install pytesser but now i'm getting the following errors. The first problem was solved by making sure that pytesser, util, errors and tesseract.exe were in the site-package file and the program didn't have to go into the pytesser folder.
>>> image = Image.open('fnord.tif')
>>> print image_to_string(image)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\site-packages\pytesser.py", line 30, in image_to_string
util.image_to_scratch(im, scratch_image_name)
File "C:\Python27\lib\site-packages\util.py", line 7, in image_to_scratch
im.save(scratch_image_name, dpi=(200,200))
File "C:\Python27\lib\site-packages\PIL\Image.py", line 1433, in save
fp = __builtin__.open(fp, "wb")
IOError: [Errno 13] Permission denied: 'temp.bmp'

Virtualenv keeps loading global site packages on Windows

I've looked around on SO, and the answers I have found to my problem haven't allowed me to solve it yet.
I want to use isolated virtualenv environments, but for one reason or another, virtualenv keeps loading global site packages, when in django's shell...
I tried to clean up PATH variables, until only c:\Python26\Scripts and c:\Python26 remain. I then create my environment.
virtualenv --distribute --no-site-packages myproject
I then activate the virtualenv. PATH is now (irrelevant vars scrapped):
PATH=E:\Development\django_projects\myproject\Scripts;C:\Panda3D-1.7.0\python;C:\Panda3D-1.7.0\bin;c:\python26\Scripts;
PYTHONPATH=C:\Panda3D-1.7.0\
So far, so good. I launch python...
>>> import django
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named django
Let's just try a module I'm sure is in my c:\python site-packages directory.
>>> import BeautifulSoup
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named BeautifulSoup
Yay! No global site packages! On to the next one then. From the command prompt, I type:
django-admin.py
And it works! But wait... I haven't installed Django yet. How is this possible?
After this, it gets even weirder... I first add these to virtualenv's activate.bat script so that Django can find my settings.
set PYTHONPATH=E:\Development\django_projects\myproject\
set DJANGO_SETTINGS_MODULE=settings.development
Now I launch django-admin.py shell and
In [1]: import BeautifulSoup
In [2]: BeautifulSoup.__file__
Out[2]: 'C:\\Python26\\lib\\site-packages\\BeautifulSoup.pyc'
How is this even possible?
Flash of insight
While typing this, I suddenly get it. .py is a file extension coupled with my c:\python26\python.exe executable, instead of the virtualenv one!
python manage.py
Traceback (most recent call last):
File "manage.py", line 2, in <module>
from django.core.management import execute_manager
ImportError: No module named django.core.management
Heh. Anyone has any idea of how to couple the .py file extension to my virtualenv's python executable instead of the system defined python executable?
A little bit of extra .bat hackery can easily fix this. My standard additions to activate.bat are:
REM custom venv settings
set PYTHONPATH=%\VIRTUAL_ENV%;%\VIRTUAL_ENV%\conf;%\VIRTUAL_ENV%\apps
set DJANGO_SETTINGS_MODULE=settings
ftype Python.File=%VIRTUAL_ENV%\Scripts\python.exe %1 %*
and to deactivate.bat
REM restore ftype
ftype Python.File=C:\tools\Python27\python.exe %1 %*
You could make a .bat file and modify PATH and PYTHONPATH in there, and then run .py from that .bat file.
Something like this i think
set PATH=C:\Python26;
python myfile.py
Ofcourse, add anything else to your path that you want.
I had the same "Access denied" problems as Dan with m0nonoke's answer on my Windows 7 setup using cmd.exe.
But I found this work around using a replacement shell TCC/LE and a customised startup file...
Under working directory create subdirectory config. In this directory
create startup file for TCC/LE called tcstart.btm
#echo off
rem Override system python binding to handle virtualenvironments
set .py;.pyc=python.exe
Now create (copy) TCC/LE shortcut on desktop and rename it
appropriately. Open Properties for shortcut and add to Target
“C:\django\config\tcstart.btm”. You probably want to set Start in to
something useful, like C:\django
Solution found in this guide on installing Django and Windows.

Resources