Comments (23)
Here's my fork: https://github.com/fredrikaverpil/fbs-tutorial/tree/multibundle
from fbs-tutorial.
We'll make it work :)
from fbs-tutorial.
Hey Fredrik,
I just tried the externalfile sample you mentioned and it works for me (see diff below). Either way, I think
I would use a custom build script based on fbs. Something like the following:
from fbs.cmdline import command
from fbs.builtin_commands import freeze
from fbs.freeze import run_pyinstaller
from os.path import dirname
import fbs.cmdline
import fbs.builtin_commands
@command
def freeze_all():
# Freeze the "Base" app:
fbs.builtin_commands.freeze()
_freeze_headless()
def _freeze_headless():
run_pyinstaller(...) # etc.
if __name__ == '__main__':
project_dir = dirname(__file__)
fbs.cmdline.main(project_dir)
The way I have it in fman is that I have such a file as build.py
in the root project directory (ie. next to requirements.txt
.) Then you can do
python -m fbs freeze_all
I think PyInstaller will complain if you run it twice with the same target directory. I would try running it with different target directories and then "brutally" copying them over each other.
I'm afraid I'm not 100% sure I understood the requirements you outlined. Are the sub-apps standalone applications as well? Or are the simply windows displayed by the Base app? If the latter, I think I would try the following directory structure:
src/main/python/
core/
<- Importable by everything else, for the "models and modules"gui/
main.py
<- The "Base" appsubapp_1/
subapp_2/
cmdline/
<- The "headless" app, importscore
main.py
<- main script for the cmdline app
But of course that's just my best guess. I hope but am not sure it will work exactly like that for you :)
Diff:
diff --git a/src/main/python/tutorial/externalfile.py b/src/main/python/tutorial/externalfile.py
index e69de29..e21af34 100644
--- a/src/main/python/tutorial/externalfile.py
+++ b/src/main/python/tutorial/externalfile.py
@@ -0,0 +1,2 @@
+def f():
+ print('hi')
\ No newline at end of file
diff --git a/src/main/python/tutorial/main.py b/src/main/python/tutorial/main.py
index 3237366..3fab972 100644
--- a/src/main/python/tutorial/main.py
+++ b/src/main/python/tutorial/main.py
@@ -1,8 +1,10 @@
+from tutorial.externalfile import f
from tutorial.application_context import AppContext
import sys
if __name__ == '__main__':
+ f()
appctxt = AppContext()
exit_code = appctxt.run()
sys.exit(exit_code)
from fbs-tutorial.
Okay, I realize I asked too many questions at once 😉
I just tried the externalfile sample you mentioned and it works for me
Ah yes, this did work... I must've done something wrong... 👍
I'm afraid I'm not 100% sure I understood the requirements you outlined.
Your example structure is almost what I'm trying to achieve, and I'll now just focus on the main problem I have. I'd like to achieve a freeze where the gui
and the cmdline
are bundled as executables and the core
is a folder with python scripts (a module).
So, something like this for the files organization:
.
└── src
└── main
└── python
├── cmdline
│ ├── __init__.py
│ └── main.py
├── core
│ ├── __init__.py
│ └── somemodule.py
└── gui
├── __init__.py
└── main.py
And something like this for the freeze (excluding all Python libraries etc):
.
├── cmdline.exe
├── core
│ ├── __init__.py
│ └── somemodule.py
└── gui.exe
Since both gui
and cmdline
imports core
, it would be nice to somehow be able to set up the development so that I can develop and run these apps but then also commence a freeze which would generate the desired bundle (and which would be possible to make an installer of).
So, to clarify; I need the core
module as pure python, as it will be interpreted by different third-party applications which all have embedded Python. They cannot use the binaries so to speak.
Does this all make sense?
EDIT: I could just copy core
into the package before making an installer out of it, I presume... but could this be avoided?
Regardless, I still need to organize the project somehow, and make it possible to run fbs run
and fbs freeze
... which is the part I haven't been able to wrap my head around... I tried your build.py
script, but I wasn't able to figure out how I could define the secondary app (cmdline
) to be built using _freeze_headless.run_pyinstaller()
.
from fbs-tutorial.
Yes, that makes sense. Thanks for clarifying :-)
I think I would simply copy the core
sources into the target/App
directory as a step of your freeze_all
command.
You're probably right. Maybe you can't use run_pyinstaller(...)
as-is. But you can more or less copy its code:
from fbs import path
from fbs.platform import is_mac
from subprocess import run
run(['pyinstaller', '--name', 'cmdline', '--noupx', '--distpath', path('target'), '--specpath', path('target/PyInstaller_cmdline'), '--workpath', path('target/PyInstaller_cmdline'), path('src/main/python/cmdline/main.py')])
Hope this is what you meant?
from fbs-tutorial.
(P.S.: You probably can also simply call your freeze_all
command freeze
. It should override fbs's one.)
from fbs-tutorial.
Very nice, thank you!
This works great, except for that I get this structure:
.
├── cmdline
│ └── cmdline.exe
└── gui
├── core (copied into place)
└── gui.exe
I'm just doing what you previously recommended:
def _freeze_cmdline():
run([
'pyinstaller', '--name', 'cmdline', '--noupx', '--distpath',
path('target'), '--specpath',
path('target/PyInstaller_cmdline'), '--workpath',
path('target/PyInstaller_cmdline'),
path('src/main/python/cmdline/main.py')
])
Do you think I could get the cmdline.exe to be built in the gui
directory?
Right now, I just copied the cmdline.exe
and cmdline.manifest
over to the gui
folder and deleted the cmdline
folder. Most likely, everything inside of the cmdline
folder needs to be copied over onto the gui
folder as well, as part of the freeze, in case it doesn't already exists there...
from fbs-tutorial.
I'm going to make a public fork out of fbs-tutorial, by the way, so that anyone who wishes to do similar stuff could look at this as another tutorial example.
from fbs-tutorial.
Do you think I could get the cmdline.exe to be built in the gui directory?
I'm not sure; You could try PyInstaller's -y
option, but I don't know if that deletes the existing directory first. If it does, I think you'll have to copy the two directories together in a separate step.
I'm going to make a public fork out of fbs-tutorial
Sounds good :-)
from fbs-tutorial.
Ok, I'll close this issue as I think I've got most questions answered ;) thanks again!
from fbs-tutorial.
Glad I could help :-)
from fbs-tutorial.
One last question on this setup... 😉 about the core
module in the example above...
-- It is being used by the gui
app and the cmdline
app. If I were to remove core
, neither apps would run when running e.g. with python -m fbs run
.
But after the freeze, core
is bundled within the frozen binaries. So, the core
module I'm copying into the build directory (before performing python -m fbs installer
) is not being used by gui.exe
or cmdline.exe
.
Now, let's speculate that I would actually want the frozen gui.exe
and cmdline.exe
to import the manually copied core
module and fail to run unless core
exists as pure python files inside of my frozen target directory.
Do you think such a thing would be possible?
from fbs-tutorial.
Yes, I would assume that if you delete the copy of core
bundled by PyInstaller, then as your app starts it will automatically pick up the source version. If not, it would probably be enough if you appended your app's directory to sys.path
.
from fbs-tutorial.
Hm. I know that all python files are bundled under the .app on macOS etc, but I'm on Windows right now. And when I look inside of target/Tutorial
, I don't see a core
folder anywhere (unless I have copied into this location myself).
But I'll try a sys.path.insert(0, PATH)
and see if that will pick up my manually copied core
module when running Tutorial.exe
.
from fbs-tutorial.
Very cool, it worked by doing a sys.path.insert
! 😄
from fbs-tutorial.
😄
from fbs-tutorial.
I just hope all of this will work once auto-updating comes to fbs 😀 because it's awesome!
from fbs-tutorial.
Hm, unfortunately, I was mistaken. I can't import the core
module using sys.path.insert
... trying to figure out a way to do it...
from fbs-tutorial.
Are you sure? I would have thought sys.path.insert(0, os.path.dirname(sys.executable))
would work.
from fbs-tutorial.
Yes. But I may have found a way with importlib
:
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(sys.executable), 'modules'))
core = importlib.import_module('core') # works, imports Tutorial/modules/core/__init__.py
# import core # doesn't work, will import Tutorial/core/__init__.pyc
Hm. It's not very nice... as you're bound to forget to not just import core
or do e.g. a from core import main
which will then somehow revert core
back to the frozen version...
from fbs-tutorial.
I can't seem to get this to work in the long run. Even if I import core
as described in my previous post, a from core import main
will "revert" the core
module back into read the compiled/frozen version of core
.
from fbs-tutorial.
Why is it important to read from the "source copy" of core
? Do users modify it?
from fbs-tutorial.
I have a Python API which I could bundle with the installer. It would be somewhat intuitive if the main apps (which uses this Python API) would actually use those files. But I guess it's not essential.
from fbs-tutorial.
Related Issues (20)
- Frozen App Crushes: No module named 'fbs_runtime' & images not included during fbs run & .ini QSettings dead
- KeyError: 'public_settings'
- Your App's Bundle ID is Empty HOT 5
- Your Bundle ID is Empty - FBS startproject error HOT 1
- raise CalledProcessError(retcode, process.args, subprocess.CalledProcessError: Command '['pyinstaller', HOT 1
- readme.md // download link outdated HOT 1
- Problem with Tensorflow and PyTorch packaging with FBS HOT 1
- Looks like work fine with python3.7 HOT 2
- FBS Freeze fail on Windows with Python3.8 HOT 1
- PyQt 5.9.2 appears broken HOT 3
- fbs installer failed on mac HOT 1
- fbs freeze failed HOT 3
- conda env can not find the 'makensis' HOT 1
- Failed to freeze HOT 1
- fpm Insall Link Broken HOT 1
- pyside6 HOT 2
- fbs freeze generated the wrong executable on windows HOT 6
- Problem with Oracledb and PyQt5 packaging with FBS
- fbs freeze got error: UnicodeDecodeError: 'gbk' codec can't decode byte 0xa8 in position 328: illegal multibyte sequence
- fbs run “Could not find the Qt platform plugin "xcb" in ""
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fbs-tutorial.