Browse Source

packaging documentation

pull/473/head
Chris 5 years ago
parent
commit
bc68b13335
4 changed files with 94 additions and 92 deletions
  1. 8
      docs/packaging/Packaging-Custom-Images.md
  2. 129
      docs/packaging/Packaging-Gooey.md
  3. 13
      docs/packaging/build-osx.spec
  4. 36
      docs/packaging/build-win.spec

8
docs/packaging/Packaging-Custom-Images.md

@ -14,7 +14,7 @@ While this works for regular executions, a little additional work is required to
To make your custom images available after packaging, you have to do two things.
**Step 1:** wrap the path to your image directory in the `local_resource_path()` function provided by Gooey. This will handle the logic of resolving the base directory in which PyInstaller unpacks your resources.
**Step 1:** wrap the path to your image directory in the `local_resource_path()` function provided by Gooey. When PyInstaller runs your application, it decompresses all the contents to a random temp directory. This function will handle the logic of resolving that directory and fetching your resources from it.
```python
from gooey import Gooey, local_resource_path
@ -31,8 +31,6 @@ def main():
import os
...
gooey_images = Tree(os.path.join(gooey_root, 'images'), prefix = 'gooey/images')
# LOOK AT ME! I AM A TREE OBJECT
image_overrides = Tree('path/to/images', prefix='path/to/images')
@ -44,8 +42,6 @@ exe = EXE(pyz,
a.zipfiles,
a.datas,
options,
gooey_languages,
gooey_images,
image_overrides, # <-- NEW
name='APPNAME',
debug=False,
@ -58,7 +54,7 @@ exe = EXE(pyz,
And then build via PyInstaller as usual.
```
pyinstaller build.spec
pyinstaller -F --windowed build.spec
```
PyInstaller will now include your images in its bundle.

129
docs/packaging/Packaging-Gooey.md

@ -1,12 +1,8 @@
# Packaging Gooey as a Stand Alone Application
>:warning: Packaging Gooey is an ongoing science. Gooey currently runs on all the major platforms, can be installed in a bajillion different ways, and has several active versions in wide usage. In short, edge cases abound. If you run into any problems, [this issue0(https://github.com/chriskiehl/Gooey/issues/259) is a great place to dump whatever errors you're running into. Just be sure to give as many details about your setup, what you've tried, and the errors you're seeing!
>:warning: Packaging Gooey is an ongoing science. Gooey currently runs on all the major platforms, can be installed in a bajillion different ways, and has several active versions in wide usage. In short, edge cases abound. If you run into any problems, hit up [this issue](https://github.com/chriskiehl/Gooey/issues/259).
>Instructions tested against Gooey 1.0.3 and pyinstaller 3.5 on Mojave 10.14.6
>This is all made possible by the work from @john174586, @jrjhealey's, and the research of numerous others.
>Pull requests with additional steps and packaging information are highly welcome.
You can package all of your programs files into a single easy to distribute executable using PyInstaller.
Packing Gooey into a standalone executable is super straight forward thanks to [PyInstaller](http://www.pyinstaller.org/). It is the only dependency you'll need and can be installed via the following.
@ -14,17 +10,11 @@ Packing Gooey into a standalone executable is super straight forward thanks to [
pip install pyinstaller
```
**Setting up the build instructions:**
**Setting up the build:**
PyInstaller uses [spec files](http://pythonhosted.org/PyInstaller/#using-spec-files) to determine how to bundle the project. These are a bit like `setup.py` files, but contain rules for how PyInstaller should bundle your whole application as a stand alone executable.
>Note: if you're still rocking Python 2.7, see [the Python2.7 section at the bottom for a few additional steps](#Python-2.7).
These provide a list of directives on how to build the package, setup hooks to run, and resources to include.
This file should be placed in the root of your project.
e.g.
This file is usually placed in the root of your project. e.g.
```
MyProject/
@ -34,112 +24,92 @@ MyProject/
- README.md
```
You can grab a pre-built spec file [here](TODO), or create a `build.spec` by hand in the root directory of your project and paste in the following:
Windows users can grab a pre-built spec file [here](TODO). For OSX users, you'll want [this one](todo).
```
# -*- mode: python ; coding: utf-8 -*-
The exact contents of the spec files will vary based on your OS, but at a high level, they'll share the same core pieces: `Analysis`, `EXE`, and, if you're on OSX, `BUNDLE`
import os
import platform
import gooey
gooey_root = os.path.dirname(gooey.__file__)
gooey_languages = Tree(os.path.join(gooey_root, 'languages'), prefix = 'gooey/languages')
gooey_images = Tree(os.path.join(gooey_root, 'images'), prefix = 'gooey/images')
from PyInstaller.building.api import EXE, PYZ, COLLECT
from PyInstaller.building.build_main import Analysis
from PyInstaller.building.datastruct import Tree
from PyInstaller.building.osx import BUNDLE
```
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['APPNAME.py'], # replace me with the app name
pathex=['/path/to/APP.py'], # replace me with the appropriate path
hiddenimports=[],
hookspath=None,
runtime_hooks=None,
)
a = Analysis(
['main.py'], # replace me with the main entry point
pathex=['/path/to/main.py'], # replace me with the appropriate path
...
)
pyz = PYZ(a.pure)
options = [('u', None, 'OPTION'), ('v', None, 'OPTION'), ('w', None, 'OPTION')]
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
options,
gooey_languages,
gooey_images,
name='APPNAME', # FIXME
debug=False,
strip=None,
upx=True,
console=False,
icon=os.path.join(gooey_root, 'images', 'program_icon.ico'))
if platform.system() == 'Darwin':
info_plist = {'addition_prop': 'additional_value'}
app = BUNDLE(exe,
name='APPNAME.app',
bundle_identifier=None,
info_plist=info_plist
)
...
name='MyCoolApplication' # replace me with exe name
console=False)
## OSX only below!
app = BUNDLE(exe,
name='APPNAME.app', # osx users replace me!
bundle_identifier=None,
info_plist=info_plist
)
```
This is the standard `build.spec` generated by Pyinstaller, but with a few additions to ensure that all of Gooey's assets get pulled in correctly during bundling.
From this spec, you'll need to make two tweaks.
The `Analysis` section is where you'll tell PyInstaller about your program. Using the build.spec from above, you'll need to make two edits to this section.
1. replace `APPNAME` in the `Analysis()` section with the name of _your_ application
2. replace the `pathex` value in the `Analysis()` section with the path to your application's root
> note: If you use additional data resources (e.g. images, data, etc..) you'll also need to explicitly add them to the EXE section. See [packaging custom images] for more info.
> note: If you use additional data resources (e.g. images, data, etc..) you'll also need to explicitly add them to the EXE section. See [packaging custom images] for more info.
Next is `EXE`. In this section you'll replace the `name` argument with what you'd like the final `.exe` to be named.
>Note: if you're providing your own icon file, EXE is where you'll provide it.
If you're on OSX, you'll have an additional `BUNDLE` section. You'll need to make one final edit here as well to control the name of the `.app` bundle that PyInstaller produces. Additionally, if you're customizing the bundle's icon, this is where you would supply the override (versus Windows, which places it in the EXE section).
**Windows Notes**
**Troubleshooting**
**I'm seeing the wrong icon on my executable**
First things first: Is Windows gas lighting you?
Windows caches icons semi-aggressively. This can lead to it showing an icon in the file explorer that doesn't actually reflect the one bundled with your program.
Once you've updated the `.spec` to reflect your program's details. All that's left to do is build the executable!
![image](https://user-images.githubusercontent.com/1408720/57576740-3e9e9f80-741c-11e9-859c-a60586097492.png)
### Running the .spec file
From the command line, run
```
pyinstaller -F --windowed build.spec
```
**OSX Notes:**
* `-F` tells PyInstaller to create a single bundled output file
* `--windowed` disables the terminal which would otherwise launch when you opened your app.
And that's it. Inside of the `dist/` directory, you'll find a beautiful stand-alone executable that you can distribute to your users.
### Troubleshooting
**My bundled Application won't work!**
First things first: _See if you can package your application **without** Gooey!_
Read and understand all of the PyInstaller docs. If you're referencing binaries or external data files, you may have to do a little extra work in your `.spec` to get PyInstaller to understand all of your dependencies.
Rebuild your bundle with `debug=True` set in the `.spec` file. This will give lots of useful output when your application bootstraps which can make pinning down the problem much easier.
Rebuild your bundle without the `-F` flag (e.g. just `pyinstaller build.spec`). This will build a directory with all of your dependencies. This can make it easier to poke around and see what PyInstaller's view of your project actually is.
### Python 2.7
**I'm seeing the wrong icon on my executable**
If you're on Python 2.7, you'll need to make one addition to your source file to ensure smooth output for Gooey. By default, the python interpreter will aggressively buffer stdout which means that rather than Gooey being able to read and display the output of your program in real time, it receives it in awkward coarsely grained chunks.
First things first: Is Windows gas lighting you?
Normally, passing the -u flag to the Python interpreter would be enough to prevent stdout buffering. However, due to an apparent quirk in PyInstaller, it seems that the -u flag never makes its way up to the interpreter, and thus the output is still highly buffered. Luckily, getting around this pretty easy.
Windows caches icons semi-aggressively. This can lead to it showing an icon in the file explorer that doesn't actually reflect reality.
Add these two lines to your source anywhere before your main() (or equivalent) method.
![image](https://github.com/chriskiehl/GooeyImages/raw/images/docs/packaging/cached-icon.png)
nonbuffered_stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
sys.stdout = nonbuffered_stdout
Right-click on the executable and select "properties." This will show you the icon that's actually associated with file. As long as everything looks good there, you're golden. Windows will catch up... _eventually_.
### Troubleshooting
**Exception: This program needs access to the screen. Please run with a Framework build of python, and only when you are logged in on the main display of your Mac.**
This happens on OSX when you neglect the `--windowed` flag during your build step.
@ -155,3 +125,4 @@ pyinstaller --windowed build.spec
```
Checkout the [Pyinstaller Manual](https://github.com/pyinstaller/pyinstaller/wiki/FAQ) for more details.

docs/packaging/build.spec → docs/packaging/build-osx.spec

@ -47,10 +47,9 @@ exe = EXE(pyz,
console=False,
icon=os.path.join(gooey_root, 'images', 'program_icon.ico'))
if platform.system() == 'Darwin':
info_plist = {'addition_prop': 'additional_value'}
app = BUNDLE(exe,
name='APPNAME.app',
bundle_identifier=None,
info_plist=info_plist
)
info_plist = {'addition_prop': 'additional_value'}
app = BUNDLE(exe,
name='APPNAME.app',
bundle_identifier=None,
info_plist=info_plist
)

36
docs/packaging/build-win.spec

@ -0,0 +1,36 @@
# -*- mode: python ; coding: utf-8 -*-
import gooey
gooey_root = os.path.dirname(gooey.__file__)
block_cipher = None
a = Analysis(['APPNAME.py'], # replace me with your path
pathex=['/path/to/APP.py'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
icon=os.path.join(gooey_root, 'images', 'program_icon.ico'))
Loading…
Cancel
Save