Open cudmore opened 2 years ago
For my users I really need to hand them a working app.
just to confirm, you can't use the bundles here right? https://github.com/napari/napari/releases (and if so, curious why not)
ModuleNotFoundError: No module named 'napari._event_loop'
Pyinstaller definitely takes some experimentation to get right, and the biggest issue is hidden imports. If you're committed to using pyinsatller, and definitely can't use our bundle. Then read through the pyinstaller docs, specifically this page: https://pyinstaller.org/en/stable/when-things-go-wrong.html, (and this section). I can't give you an immediate answer, since it just took a lot of trial and error for me in the first place.
You'll likely need to modify the hook_napari.py file...
but ultimately, the bundled app we intend to provide support for is the ones on our release page, not this one.
Thanks for your always prompt and thorough response!
My motive here is I want to create a bundled installer for a desktop app that uses Napari as a viewer. With this I can rapidly extend Napari functionality while I wait for my proper plugins to mature.
On the flip-side, I am actively writing proper plugins for Napari. AS these become mature, my users can use the awesome prebuilt Napari installers.
Can I get a link to a description of how Napari is building it's one-click install bundles? Would love to add that to my work-flow.
we have two methods. one based on briefcase: https://github.com/napari/napari/blob/main/bundle.py and one based on conda: https://github.com/napari/napari/blob/main/bundle_conda.py
you can see how they are used on GitHub actions here: https://github.com/napari/napari/blob/main/.github/workflows/make_bundle.yml and here: https://github.com/napari/napari/blob/main/.github/workflows/make_bundle_conda.yml
For posterity, here's a --onefile
spec that worked for me; part of the solution was to include napari._event_loop
in the hiddenimports
list
python: 3.10
napari: 0.4.19
pyinstaller: 6.8.0
# -*- mode: python ; coding: utf-8 -*-
import sys
from PyInstaller.building.api import COLLECT, EXE, MERGE, PYZ
from PyInstaller.building.build_main import Analysis
import napari
sys.modules["FixTk"] = None
NAME = "my-napari-app"
WINDOWED = True
DEBUG = True
UPX = False
def get_icon():
logo_file = "logo.ico" if sys.platform.startswith("win") else "logo.icns"
return logo_file
def get_version():
if sys.platform != "win32":
return None
from PyInstaller.utils.win32 import versioninfo as vi
ver_str = napari.__version__
version = ver_str.replace("+", ".").split(".")
version = [int(x) for x in version if x.isnumeric()]
version += [0] * (4 - len(version))
version = tuple(version)[:4]
return vi.VSVersionInfo(
ffi=vi.FixedFileInfo(filevers=version, prodvers=version),
kids=[
vi.StringFileInfo(
[
vi.StringTable(
"000004b0",
[
vi.StringStruct("CompanyName", NAME),
vi.StringStruct("FileDescription", NAME),
vi.StringStruct("FileVersion", ver_str),
vi.StringStruct("LegalCopyright", ""),
vi.StringStruct("OriginalFileName", NAME + ".exe"),
vi.StringStruct("ProductName", NAME),
vi.StringStruct("ProductVersion", ver_str),
],
)
]
),
vi.VarFileInfo([vi.VarStruct("Translation", [0, 1200])]),
],
)
a = Analysis(
["main.py"],
hookspath=["hooks"],
hiddenimports=[
'napari._event_loop',
],
excludes=[
"PyQt5",
# "PyQt6",
"FixTk",
"tcl",
"tk",
"_tkinter",
"tkinter",
"Tkinter",
"matplotlib",
],
)
pyz = PYZ(a.pure)
## --onefile
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name=NAME,
debug=DEBUG,
upx=UPX,
icon=get_icon(),
version=get_version(),
bootloader_ignore_signals=False,
strip=False,
upx_exclude=[],
runtime_tmpdir=None,
console=(not WINDOWED),
disable_windowed_traceback=False,
argv_emulation=True,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
Trying to get this to work. For my users I really need to hand them a working app. They can not deal with a command line (not today, not ever).
My build system:
Still trying to figure out how to set up an easy to use Python installation on the M1 (arm64) chip. I currently can't get PyQt5 to install via pip so need to use conda.
Here are my steps to creating a conda env
When I run the napari-app.app, I get this?