How to un pyinstaller converted python app with Shiny for Python

Question:

I downloaded and installed Python 3.10.6 on windows 10 pro, installed Shiny for Python, created the sample app and run it. This worked fine.

I installed pyinstaller and converted the app to an exe. I tried to run the app it threw (please see below).

Does anyone know if this can work and if so how?

This is the file2.spec that worked:

# -*- mode: python ; coding: utf-8 -*-


block_cipher = None
import os
# /c/Users/raz/AppData/Local/Programs/Python/Python310/Lib/site-packages/
shiny = os.path.abspath("../AppData/Local/Programs/Python/Python310/Lib/site-packages/shiny")


a = Analysis(
    ['file2.py'],
    pathex=[],
    binaries=[],
    datas=[('app.py', '/'), (shiny,'/shiny')],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    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='file2',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=True,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)

This below did not work:

raz@rays8350 MINGW64 ~/shiny
$ cat app.py
from shiny import App, render, ui

app_ui = ui.page_fluid(
    ui.h2("Hello Shiny!"),
    ui.input_slider("n", "N", 0, 100, 20),
    ui.output_text_verbatim("txt"),
)


def server(input, output, session):
    @output
    @render.text
    def txt():
        return f"n*2 is {input.n() * 2}"


app = App(app_ui, server)

raz@rays8350 MINGW64 ~/shiny
$


raz@rays8350 MINGW64 ~/shiny
$ ../AppData/Local/Programs/Python/Python310/Scripts/shiny.exe run --reload dist/app/app.exe
INFO:     Will watch for changes in these directories: ['C:\Users\raz\shiny\dist\app']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [23368] using StatReload
Process SpawnProcess-1:
Traceback (most recent call last):
  File "C:UsersrazAppDataLocalProgramsPythonPython310libmultiprocessingprocess.py", line 314, in _bootstrap
    self.run()
  File "C:UsersrazAppDataLocalProgramsPythonPython310libmultiprocessingprocess.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "C:UsersrazAppDataLocalProgramsPythonPython310libsite-packagesuvicorn_subprocess.py", line 76, in subp
rocess_started
    target(sockets=sockets)
  File "C:UsersrazAppDataLocalProgramsPythonPython310libsite-packagesuvicornserver.py", line 60, in run
    return asyncio.run(self.serve(sockets=sockets))
  File "C:UsersrazAppDataLocalProgramsPythonPython310libasynciorunners.py", line 44, in run
    return loop.run_until_complete(main)
  File "C:UsersrazAppDataLocalProgramsPythonPython310libasynciobase_events.py", line 646, in run_until_complet
e
    return future.result()
  File "C:UsersrazAppDataLocalProgramsPythonPython310libsite-packagesuvicornserver.py", line 67, in serve
    config.load()
  File "C:UsersrazAppDataLocalProgramsPythonPython310libsite-packagesuvicornconfig.py", line 479, in load
    self.loaded_app = import_from_string(self.app)
  File "C:UsersrazAppDataLocalProgramsPythonPython310libsite-packagesuvicornimporter.py", line 24, in import_
from_string
    raise exc from None
  File "C:UsersrazAppDataLocalProgramsPythonPython310libsite-packagesuvicornimporter.py", line 21, in import_
from_string
    module = importlib.import_module(module_str)
  File "C:UsersrazAppDataLocalProgramsPythonPython310libimportlib__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 992, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1004, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'app'
Asked By: Ray Tayek

||

Answers:

Okay… So here are the steps I took to make it work.

  1. open new directory (my_new_dir)
  2. python -m venv venv
  3. venvscriptsactivate.bat
    • or your OS’s equivalent.
  4. pip install pyinstaller shiny
  5. open new file and paste this code in (file1.py)

file1

from shiny import App, render, ui
app_ui = ui.page_fluid(
    ui.h2("Hello Shiny!"),
    ui.input_slider("n", "N", 0, 100, 20),
    ui.output_text_verbatim("txt"),
)
def server(input, output, session):
    @output
    @render.text
    def txt():
        return f"n*2 is {input.n() * 2}"
app = App(app_ui, server)
  1. open a second new file next to the first (file2.py) and copy paste
file2.py
import os
import sys
from shiny._main import main
path = os.path.dirname(os.path.abspath(__file__))
apath = os.path.join(path, "file1.py")

# these next two lines are only if you are using Windows OS
drive, apath = os.path.splitdrive(apath)
apath = apath.replace("\","/")
# 

sys.argv = ['shiny', 'run', apath]
main()
  1. pyinstaller -F file2.py
    • this will create a file2.spec file open it and make the changes in the code below:

file2.spec

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None
import os
                       # use OS equivalent for path below
shiny = os.path.abspath("./venv/Lib/site-packages/shiny") 

a = Analysis(
   ...
   ...
   datas = [('file1.py', '/'), (shiny,'/shiny')]  # fill in the datas value
   ...
   ...

Last step:

  1. pyinstaller file2.spec

At the end of this your top level directory should look like this:

build
dist
venv
file1.py
file2.py
file2.spec

That is what worked for me. And the exe is in the dist folder.

If you want to change the name of the executable or the icon or any of that stuff that can all be done in the spec file and instructions can be found in the pyinstaller docs

Answered By: Alexander
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.