New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
macOS console app bundle doesn't launch #5154
Comments
Does the system.log say anything useful? When I had that error recently it was because of a code signing issue. |
You're using |
So is there no way to make a .app bundle that runs a non-GUI console app? In that case, I’d like to turn this into a feature request. I want users to be able to double run with a double click. |
Yeah, just omit the |
But I think —windowed is required to create the .app bundle |
Uggh possibly. I thought |
The binary cannot be run by a double click on macOS. You have to run it from a Terminal. This makes it hard for non-technical users. |
Then it's broken. You should be able to just click on it. #5109 may be the cause. |
Wow, I never knew you could run binaries this way on macOS. My filename had a dot (.) in it and after removing that, it does run with a double-click. That seems to be a macOS limitation, not a problem with PyInstaller. I would still prefer using a .app bundle for a few reasons:
|
@rokm Do you know if a console based (as opposed to an app with a GUI) |
I found an ugly hack to make this work. The binary is located at
Now it runs my code in a new Terminal window. Don't forget |
From my experiments, it would seem that The minimal test example used here, when ran as an Using a wrapper script to run the executable in a |
I've added the following code to the end of the spec file, and this seems to work okay. It would be good to have this integrated into PyInstaller, but I don't know the best way to do that. One problem with this method is the app bundle still will not launch if it has a space in the filename or anywhere in the path. ## Make app bundle double-clickable
import plistlib
from pathlib import Path
app_path = Path(app.name)
# read Info.plist
with open(app_path / 'Contents/Info.plist', 'rb') as f:
pl = plistlib.load(f)
# write Info.plist
with open(app_path / 'Contents/Info.plist', 'wb') as f:
pl['CFBundleExecutable'] = 'wrapper'
plistlib.dump(pl, f)
# write new wrapper script
shell_script = """#!/bin/bash
dir=$(dirname $0)
open -a Terminal file://${dir}/%s""" % app.appname
with open(app_path / 'Contents/MacOS/wrapper', 'w') as f:
f.write(shell_script)
# make it executable
(app_path / 'Contents/MacOS/wrapper').chmod(0o755) |
@llamafilm That looks good and certainly could turn into a feature. Possibly it could be implemented in a As for you spaces in paths problem, you just should be able to wrap it in either shell_script = """#!/bin/bash
dir=$(dirname $0)
open -a Terminal "file://${dir}/%s"
""" % app.appname |
Started work on this feature to create a new class |
Can one please give a summary of what the exact cause is and how this script helps solving this? (this might also be helpful for documenting the pull-request later). Thanks. |
The macOS app bundles don't seem to open terminal window by themselves when you run them, e.g. by double clicking on them in Finder. (In contrast to, for example console Windows application that will open a terminal if run by double-clicking on the executable. So the behavior of macOS .app bundles is like that of Windows noconsole applications, but the reporter would like to have it behave like a console one). The idea here is that for macOS .app bundles of CLI applications, we add a launcher script that explicitly opens a macOS Terminal and runs the executable in it. |
Inserting comments of @bwoodsend from discord over here for context:
|
I wish I could. After studying this for a few hours, I still cannot figure out why the app doesn't launch. I can build my own app bundle by hand containing nothing more than Info.plist and an executable shell script and that works fine. So this workaround just changes the app executable to a wrapper shell script, which then opens the real binary in Terminal. This error message:
is not very specific; it can happen for many reasons. Sometimes it can be fixed by reloading Launch Services database:
Each user has a separate Launch Services database, so if you run as root (for Initially, the system log shows an error:
This means the app is not code-signed, and I think it's harmless. It can be fixed with:
There is nothing helpful in the system log. RunningBoard watches the process without managing it, so I don't think that subsystem is responsible for the error.
I don't see anything helpful in Expand for details.
|
The reproducer from original report: print('hello world')
input() is crashing because
If the example is expanded with top-level error handling and logging, e.g.: try:
print('hello world')
input()
except Exception as e:
with open('/Users/username/error.log', 'w') as f:
f.write(f"{e}\n") you will find that So the application does launch, but it crashes with unhandled exception, and without console, you get no feedback. Once you ensure that there is console (launcher script that runs executable in Terminal), |
Thank you @rokm. I forgot you said that, that's what led me to write the wrapper script in the first place! |
Happy new year! So I'm trying to think of a CLI argument name that is clear enough. Initial suggestion was Now I am thinking to use |
Why not use the existing |
@llamafilm I thought about that, so in the docs the As a result it will have to be a new option otherwise it would break existing behaviour. In this case I will stick with |
I'd be against using |
The comments in this thread let me solve the problem I was having with the .app not launching, but the executable inside working fine. I had literally spent days trying to figure this out. I think it would be very helpful to include a note in the docs that if you see "LSOpenURLsWithRole() failed with error -10810" when running the app (but the executable inside works fine), then your app is crashing -- probably due to the lack of stdin or a directory your app is writing to being read-only for sandboxed apps. One way to debug it is to use printf-stye debugging, but writing to a log file (since stdout/stderr don't go anywhere). Thank you! |
Any update on this? The workaround by @llamafilm (#5154 (comment)) seems to work, but is quite a pain to do after each build. Also, it would be nice if there was a way to hide the console window in cases where we are building a gui-only application. |
hey @meichthys I'm working on a revision of the PR this weekend, sorry for the delay |
@motatoes Do you know if the revision was implemented yet? I haven't had the chance to rebuild my dev environment yet to test. |
This issue is not specific to pyinstaller and it might not be related to |
Hi, I have the same issue with my app, it runs in terminal but does not run when bundled in .app format, I realized xprotectservice runs together with the .app, Can antimalware protection of mac os be preventing it from running? |
There are other differences between running a .app by double clicking it and launching the executable inside it from the terminal. A .app does not run with the environment set in shell initialisation scripts like There's also a chance that .app is a red herring and you've just got some local resource path screwed up. You can verify this just by moving your application to somewhere random, open a terminal in another random folder then launch your application using its full path via that terminal. If it still runs fine then this is not the problem. If that gets you nowhere then I suggest following Rok's advice. |
My issue was resolved when I use pathlib to get the path of the data files I include when building. Here is a quick method that solved my issue. So everytime I dont use this method, my app crashes (works fine when opened with terminal), so I had to find all of the data read/writes and fix them one by one. def getResourcePath(relative_path):
rel_path = pathlib.Path(relative_path)
dev_base_path = pathlib.Path(__file__).resolve().parent
base_path = getattr(sys,"_MEIPASS",dev_base_path)
return base_path / rel_path Then I used this function to get path of the required data to run my app. Credit goes to this tutorial p.s. I use Macbook w/ M1 Pro |
hi, I tried your method. Found But I don't understand how to modify |
I am a beginner. I try to use your script, run it in the terminal, In the end just opened the terminal and didn't run the '.app' |
Come and save my week! I tried using the method above, but it didn't work!
This will only open the executable in the terminal. didn't get the .app to run I packaged with virtual environment pyhton3.9 + pyinstaller. Running the .app on the real python2.7 environment of the system can run normally. I packaged with virtual environment pyhton2.7 + pyinstaller. Running the .app on the system's real python2.7 environment does not work. Ultimately I hope to use python2.7 to complete this task! |
We're not here to save you from your problems...
Is your executable within the .app bundle named If your bundle is called
mv program.app/Contents/MacOS/program program.app/Contents/MacOS/program.orig
#!/bin/bash
dir=$(cd "$( dirname "${0}")" && pwd )
open -a Terminal "file://${dir}/program.orig" the script should be running the original (renamed) executable, so make sure you get it right. Now save that script as
chmod +x program.app/Contents/MacOS/program
The versions of pyinstaller that support python 2.7 are not supported anymore (same as python 2.7 itself), so if you want to use python 2.7, you're on your own. |
Same problem with OSX Ventura. @avishayil, have you found a solution? |
Haven't found a solution. Had to go via the single executable way rather than .app file |
I was having this exact same problem and found a way to get it sorted out even though it is more like a hack, anyway this is what is working for me.
I know it's not related to pyinstaller but it's working for my purposes, not sure if this approach would be even something pyinstaller team would consider adding to the app generation process but at least it's a workaround for some use cases. |
Description of the issue
I'm building in a clean virtualenv with
pyinstaller test.py --windowed
I can't launch the .app bundle by double-clicking nor with
open ./test.app
in Terminal.It works fine if I run
./test.app/Contents/MacOS/test
Context information (for bug reports)
Output of
pyinstaller --version
:4.0
Version of Python: 3.7.7
Platform: macOS 10.14.6
try the latest development version. No change.
follow all the instructions in our "If Things Go Wrong" Guide. Done.
A minimal example program which shows the error
Stacktrace / full error message
In the Console I see these errors, which aren't very helpful:
So I tried adding an empty PlugIns directory. This makes the "non-fatal" error messages go away, but the app still doesn't launch.
The text was updated successfully, but these errors were encountered: