I'm trying to make a standalone, double click macosx app from a python module that has the
if __name__ == __main__
line in it to run. However, whenever I try to bundle it with something like py2app or pyinstaller, if I make an app bundle, a terminal window doesn't launch to run the program. Any idea on how to get around this? The terminal window needs to open in order to accept some user input. Let me know if more info is needed, this is the first time I've ever tried doing this.
P.S. I was able to get this to work for windows and package it within an installer for distribution.
Ok, I figured it out. Since building an app bundle from scratch is a bit tricky on a mac, it's better to find a program that will build it for you, I used applescript to accomplish this.
First, you need to build your executable file which is coming from the python code. I used pyinstaller with the --onefile option. so to build your executable use the command:
$pyinstaller --onefile yourPythonProgramYouWantToBuild.py
Once that's built, double click the file or open it with terminal to check that it works, all required code from various libraries have been included etc. If that works, onto the next step.
Open up applescript and set up a new script.
Here's how I got the thing to work
1) the applescript get's the directory its in
2) the compiled executable is going to be (manually) placed in the app bundle and the script inside the app is going to know where it is in the app bundle
3) the script finds the exact path to the executable, and tells the Terminal application to run it
Ok so how to do that?
Make a new applescript, and just put some dummy code in it, for example :
display dialog "Hello, world!"
Next, save this applescript as a app bundle. Go into the fresh app bundle you just made and navigate within the app's package contents Contents->Resources->Scripts->main.scpt. Now open up the main.scpt file and begin to edit it.
In your main.scpt, first find the directory where the applescript is
tell application "Finder"
set current_path to container of (path to me) as string
end tell
However if you throw in a display dialog current_path in the apple script, when you run that from the app bundle, you'll find that it won't take you all the way inside the app bundle. For example, if you were running the app from the desktop the path you would get would be something like ~/Desktop/, which is not what we want, because we need to get the path inside the app. So next we need to append some stuff to the end of that in order to get to the good stuff inside the app bundle. Use a command similar to this:
set current_path to current_path & "TheNameOfThe.app" & ":" & "theNameOfYourCompiledExecutable"
Now we have a path to an executable that (might be) in your app's bundle. Now, make a POSIX path and tell terminal to run a the script.
set a to POSIX path of current_path
tell application "Terminal"
do script a
end tell
The last thing to do is to open up the app package contents and copy your onefile executable to the correct place within the app bundle. Change the app icon as necessary.
Related
This is a bit of a loaded question but I will set it up in order. I'm sure the answer is really simple and that I just wasn't aware about certain things...
1st: I have 2 python files. One is named main.py which is the program UI. The second is the program that the main.py program runs. It does this by grabing the python file from a specific directory.
2nd: I did pip install pyinstaller which is what I used to create the executable for main.py
3rd: Once everything is in the folder with the executable UI app, and I run the executable, I have the option to start and stop. When I press Start on the UI, it is supposed to run the program that it is connected to the start button.
The primary issue is that when I do press run, behind the UI exe window, there is a terminal, that displays dependency_name not found and it basically sits there. The dependencies are in a venv folder. The program the UI is for imports those. In the IDE, this works perfectly. The second it becomes standalone, it no longer can find those dependencies.
Both Python files, the exe, the venv folder (dependencies inside), and some other icons and images are all in one project folder that ideally should work alone with the exe for main.py inside.
Does anyone have an idea of what I might be doing wrong or maybe a step I missed?
I am using PyInstaller to bundle my multi-module Python app into a one-file exe. The entry point for this app is a module extending win32serviceutil.ServiceFramework -- so this is meant to run as a Windows service. Problem arises when I try to furnish a user configurable logger ini file with this app. In my main module, I set up the logger thus,
log_file_path = path.join(path.dirname(path.abspath(__file__)), 'logging.conf')
logging.config.fileConfig(log_file_path)
My PyInstaller command is the following:
pyinstaller -F <main-file>.py -n <exe-name> --hidden-import=win32timezone --add-data "logging.conf;."
Once packaged, I install the produced exe as a service and it successfully registers as a Windows service. However when I attempt to start it, it fails.
The interesting bit is that an empty log file is created in my configured location. So this implies that 1) The application did read my config file, and 2) There's no permissions issue here. Has anyone tried to set up something like this that could help shed light on what I might be missing?
When using the one-file option with PyInstaller, we cannot validly use the __file__ variable in our code to identify the bundled app or its location. Instead, PyInstaller sets special system variables at runtime, like sys._MEIPASS and sys.executable; which specify the temporary folder created by the bootloader to run the app, and location of the frozen executable (the bootloader), respectively.
Once I changed my path manipulation to use these variables to locate the log config file, the file is successfully read and the service works.
I'm trying to learn how to use pyinstaller to make an executable. I wrote a little script in 2.7 as a test. Print 'test" and named it test-print. When I click on the executable in the Build folder a cmd screen flashes, and that all she wrote. I tried adding a x = raw_input('input something: ') hoping that would cause the cmd screen, or some kind of screen to persist, but to no avail. I know this is basic stuff, but a voice of experience would be most helpful.
F
First try running the command from a command line (terminal) so you can see what happens. Not from inside any IDE.
If you created the script in a MSWindows environment, be sure your PATH includes the executable (or explicitly give the path to the script).
In Linux/Unix, be sure to enable execute permission for the script. chmod +x scriptname
In pyinstaller the actual executable is located in the dist folder. I assume you did not use pyinstallers "--onefile" switch so once you finish compiling, navigate to dist then test-print. Afterwards look for test-print.exe in that folder. That is your executable.
I can not launch a python script from a .desktop launcher created on Linux Mint 17.1 Cinnamon.
The problem is that the script will be launched in the wrong path - namely the home folder instead of the directory it is placed in. Thereby it can not find other vital files accompanying it in its folder and hence does not work.
To examine that misbehaviour I created a short script to check the folder a python script is executing in:
#!/usr/bin/env python
import subprocess
import time
subprocess.call(["pwd"], shell=True)
time.sleep(7) # to get a chance to read the output
Executing it from its own folder gives the output:
/home/myusername/PythonProjects
I am setting a desktop launcher via Nemo's menu. Now executing the same script yields:
/home/myusername
I do not understand this behaviour. How could I create a working desktop launcher for my python script?
The page describes the format of .desktop files.
You may note the "Path" element, which specifies the working directory for the file to be run in. In your case you would want a desktop file that specified
Path=/home/myusername/PythonProjects
If Nemo doesn't allow you to set the Path element you may need to edit the desktop file by hand. The .desktop files are text files and you can probably find them in /home/myusername/.local/share/applications/
I had developed an app in python on mac osx for opening different file types on double-clicking any file. Then I converted into app by using py2app. py2app creates a myapp.app within dist folder. I moved myapp.app from dist folder to Applications location. Now, I am able to open any file through myapp just by double-clicking on it. Now, I want to make it work in such a way that, I don't need to drag and drop myapp to Applications location,it should automatically install on system.
You can use packagemaker. It makes myapp.pkg file that when double-clicked installa an app in Applications location.
py2app has a "--dist-dir" option for selecting the output directory (default is "diet"). That said, I have never tested using that option for installation in a directory containing other programs and don't know if "python setup.py py2app --dist-dir=/Applications" is save to use.
The alternative is to use a script that copies the application to /Applications (a simple python script, a shell script, or even a distutils command in your setup.py file that invokes py2app and then copies the resulting application to the right location).