I'm asking help today because I'm new to Tkinter and Pyinstaller (and python in general) and I'm having troubles with it.
I have a simple app working with sqlite, tkinter and pyinstaller to compile all of this in an executable program, the entrance point of my program is a file named main.py
This file calls all the dependancies (like the sqlite module for python, tkinter and my other files like classes etc...)
I made a very simple interface, with a Hello World in a tkinter label and a button to go to page 2 which displays page2 (also in a label), just to see if I'm capable of making it all run and compile all of these pieces together.
I can run it throught my shell executing it like : python main.py and everything is working fine.
But when I run pyinstaller on my linux machine, and start executing the program, nothing appears, my database.db (sqlite database file) is created but I don't have any interface like when I run it with my shell. The thing is getting even worse on windows where, once I've my .exe it just opens a shell and crash after few seconds, not even creating the database.
What I did is I created a 'log file', in which I write the steps of the program.
As you can see on the following picture, the 2 first prints are wrote in my log file (on linux), so I think it crashes when I try to create the window.
If any of you have an idea on what I do wrong, I would really appreciate help :)
General
From the PyInstaller manual:
Before you attempt to bundle to one file, make sure your app works correctly when bundled to one folder. It is is much easier to diagnose problems in one-folder mode.
As the comments suggested, use a catch-all try/except block to log all exceptions to a file. That is probably the best way to see what is really happening. Make sure that the logfile is created in an existing location where you have the necessary permissions.
I would suggest to take advantage of the built-in logging module instead of creating your own. It can e.g. automatically add from which file a log line was created.
IMHO, it is probable that the failures on Linux and ms-windows have completely different causes. You should probably treat them as different issues.
Linux
When you use single file mode, that file is unpacked into a temporary folder, probably somewhere in /tmp. Some Linux distributions mount the /tmp filesystem with the noexec flag. This is incompatible with PyInstaller.
ms-windows
On windows, there are basically two different Pythons; python.exe and pythonw.exe. Basically it is one of the quirks of windows that this is necessary. The latter is for GUI programs like tkinter programs. A tkinter script should not show a cmd window. So I'm guessing that PyInstaller calls your command with python.exe instead of pythonw.exe. From the manual:
By default the bootloader creates a command-line console (a terminal window in GNU/Linux and Mac OS, a command window in Windows). It gives this window to the Python interpreter for its standard input and output. Your script’s use of print and input() are directed here. Error messages from Python and default logging output also appear in the console window.
An option for Windows and Mac OS is to tell PyInstaller to not provide a console window. The bootloader starts Python with no target for standard output or input. Do this when your script has a graphical interface for user input and can properly report its own diagnostics.
As noted in the CPython tutorial Appendix, for Windows a file extention of .pyw suppresses the console window that normally appears. Likewise, a console window will not be provided when using a myscript.pyw script with PyInstaller.
Also, on windows it can matter which Python distribution you're using. I used to be a fan of Anaconda, but lately I've come to prefer the python.org version because it gives me less headaches. On anaconda Python I had the problem that tkinter programs would not launch without showing a cmd window, whatever I tried. Only switching to python.org Python solved that problem.
Related
I am developing a simple standalone, graphical application in python. My development has been done on linux but I would like to distribute the application cross-platform.
I have a launcher script which checks a bunch of environment variables and then sets various configuration options, and then calls the application with what amounts to python main.py (specifically os.system('python main.py %s'% (arg1, arg2...)) )
On OS X (without X11), the launcher script crashed with an error like Could not run application, need access to screen. A very quick google search later, the script was working locally by replacing python main.py with pythonw main.py.
My question is, what is the best way to write the launcher script so that it can do the right thing across platforms and not crash? Note that this question is not asking how to determine what platform I am on. The solution "check to see if I am on OS X, and if so invoke pythonw instead" is what I have done for now, but it seems like a somewhat hacky fix because it depends on understanding the details of the windowing system (which could easily break sometime in the future) and I wonder if there is a cleaner way.
This question does not yet have a satisfactory answer.
If you save the file as main.pyw, it should run the script without opening up a new cmd/terminal.
Then you can run it as python main.pyw
Firstly, you should always use .pyw for GUIs.
Secondly, you could convert it to .exe if you want people without python to be able to use your program. The process is simple. The hardest part is downloading one of these:
for python 2.x: p2exe
for python 3.x: cx_Freeze
You can simply google instructions on how to use them if you decide to go down that path.
Also, if you're using messageboxes in your GUI, it won't work. You will have to create windows/toplevels instead.
I am new to python programming and development. After much self study through online tutorials I have been able to make a GUI with wxpython. This GUI interacts with a access database in my computer to load list of teams and employees into the comboboxes.
Now my first question is while converting the whole program into a windows exe file can I also include the .accdb file with it...as in I only need to send the exe file to the users and not the database..if yes how.
My second question is... I actually tried converting the program into exe using the py2exe (excluding the database...am not sure how to do that) and I got the .exe file of my program into the "Dist" folder. But when I double click it to run it a black screen (cmd) appears for less than a second and disappears. Please help me understand the above issue and resolve it.
am not sure if I have a option of attaching files...then I could have attached my wxpython program for reference.
Thanks in advance.
Regards,
Premanshu
The console could possibly appear if you used the 'console' parameter to setup(). Switch to 'windows' instead if that is the case. Can't say for sure without seeing your setup.py script. Possibly your app could also be opening console, but again hard to say without seeing source. One thing to check is to make sure you are not printing anything to stdout or stderr. You might want to redirect all of stdout and stderr to your log just in case, and do this right at the top of your start script so that if some 3rd party import was writing to stdout you'd be able to capture that.
The db is not part of your executable, so py2exe will not do anything with it. However, you should probably package your application with an installer, and you can make the installer include the db and install it along with the executable.
I am trying to integrate a complex python application (with a custom python interpreter shipped along) for OSX. In order to handle a set of issues due to cross platform requirements, I created a .app bundle pointing at a shell script with its CFExecutable entry in Info.plist. This works, and the invoked shell script starts up the actual application binary. However, I have the following problems:
The .app icon bounces endlessly on the dock, never reaching the "activated" status. I guess it's because the shell script does not terminate. This dock entry has the correct "application icon"
When the binary executable is invoked by the script, a new Dock entry appears with a generic python icon. This icon successfully starts up and stops bouncing as the application starts up.
When I try to kill the first Dock entry via Force quit, the actual application still keeps running, as it's clearly controlled by the second entry on the dock.
Is there a way to have this setup behave more naturally? Do I need to ditch shell script for an objective C wrapper? If I have to use a obj-C wrapper (instead of a shell script) to spawn my application, how can I prevent the same spawning of a secondary icon to happen?
Edit: note, I am not running a python script. I am running a custom made python interpreter. py2app is not what I need.
It seems like many use py2app for this purpose with success.
If that doesn't work for you, the Java equivalent I'm famailar with, appbundler, does create a mach-o executable stub to fire things off. You might check out how they do things, particularly their main.m.
I solved the problem, and in hindsight it was rather trivial. In the shell script, I need to invoke my binary with exec, so that the running bash process is replaced (a la execve()) rather than spawning a new process. The only problem is that my interpreter now replaces the icon with the stock one, but I have only one icon in the dock now, and behaves naturally.
I'd like to write cross platform Python scripts that are GUI frontends for command line programs. The problem is I know a few Mac users who think that using the terminal will have the same effect as throwing their computer off the top of a skyscraper. In Linux and Windows it's easy enough to setup a Python script so the user can double click an icon and the script will start without opening any extra windows. Is there an easy way to do this with OS-X? Would the user have to install a different Python than the one that comes with OS-X? I haven't been able to find a definitive answer.
You might want to look at Platypus. It's a freeware app for generating apps which wrap scripts.
Another way to do something like that is using Automator or even AppleScript Editor. Either can produce an application which just runs a script.
Update:
For Automator: Launch Automator, select the Application template, type "script" in the search field, double-click Run Shell Script, switch the shell pop-up menu to /usr/bin/python, type/paste your Python script into the text field. Or, leave the pop-menu on /bin/bash and just write an invocation of an external script in the text field. Save as an application.
You can also view help from its Help menu.
For AppleScript, launch AppleScript Editor, type the following as the script:
do shell script "/usr/bin/true"
Replace /usr/bin/true with the path to whatever script you like. Save as an application.
Again, there's help in the Help menu.
py2app does this with aplomb. You make your Python script, use whatever dependencies you need (wx, Tkinter, etc.) and py2app makes you a standalone app bundle that will run in any modern OS X environment. It bundles Python too, so you can use any Python you want (not just the system default).
The downside is that the generated apps might be large, up to 50MB if you have a lot of dependencies (though that is somewhat of an extreme).
There are two ways to do this:
Click on a script.
Press command-i to open the "get info" window.
Expand the "Open With" section (if it isn't already).
Choose "Python Launcher" from the drop-down menu.
Click "Change All" if you would like ALL Python scripts to launch when double clicked.
Possibly open Python Launcher and uncheck "Run in a Terminal window"
This will work for this machine only, so it is less portable than the following. Why? Because the default for opening a document type varies depending on what is installed (XCode and/or IDLE will both take over opening a .py file).
Method Two:
Validate the Interpreter Directive, that's the first line of the file. I suggest using /usr/bin/env python3. This will run the first python3 interpreter that is on the users path.
Make the script executable chmod a+x <script_name> from the Terminal.
Change the extension from .py to .command (this will be opened by the Terminal).
Use zip or tar for distribution so that the permissions do not get mangled.
This method will open a Terminal window, but when the Python window is closed the terminal window will also close.
If your script has dependencies outside of the standard library, then you should provide a second .command file to install those. This may make things more complicated, but using pip3 install --user <list of dependencies> should minimize complications.
I recently tried to convert one of my python scripts (used for file-systems I/O) to a executable file by using py2exe. However, after successfully generating the .exe file from my python script, I am no longer able to copy and paste any text(or anything for that matter) from other windows apps to my python app console (when I run the script/app from the .exe file). When right click the mouse now, the access window does not pop up any longer. Does anyone know how I can get around this issue?
Thanks,
A.L.
Right-clicking a console window is a "special feature" of the command line interpreter of Windows Vista and above. It doesn't work on any other command-line tool, so it doesn't longer works for your converted script. You can still access it using the windows menu (small icon in the title bar or Alt+Space).
You could try to get the right-click feature back by messing around with Windows API calls - but the more convenient possibility would be to enable pasting using Ctrl+V and forget about the window menu. A good candidate is PyReadline - install the package and run this at the beginning of your script:
import readline
readline.parse_and_bind("control-v: paste")