I am building a fairly complex application using Python and PySide. Finally the day of the release is nearing so I want to build this application as an exe.
However, I have a strange problem on my hands. I've used PyInstaller (using version 2 by the way) in the past and never had this happened to me.
Basically, when I build the application with the --console
flag, it works fine - but it opens the console window. When I build the application with the window flag (-w
), it doesn't work fine. It starts and everything, but there are all these weird glitches. For example, loading a text file often raises the BadFileDescriptor
error (which doesn't happen in console mode), and the application crashes after performing a certain task. What's worse is that the task is a loop, and it performs fine the first time, but when it starts working again, it crashes.
When I looked at the minidump file there were some errors about memory access violation of QtGui4.dll file. Again, this doesn't happen in console mode.
Anyone have any ideas?
When I create an app with pyinstaller (setting onefile, onedir don't matter) and run the app, the app just opens a console window and without any message close the window. I tested it with Conda 32-bit, Python 3.6.4/3.7.4 and pyinstaller 3.4/3.5/3.6 and everytime a get the same behaviour.
pyinstaller "C:\Documents and Settings\project\myscript.spec" A full list of the pyinstaller command’s options are as follows: Name of scriptfiles to be processed or exactly one .spec file. If a .spec file is specified, most options are unnecessary and are ignored. Show program version info and exit.
Using --windowed on Pyinstaller disables output for GUI. (Or what else can I use) Is there a solution to this? I made my first ever GUI, and it was a currency converter (with the help of PAGE and google).
If you need to distribute your application for more than one OS, for example both Windows and macOS, you must install PyInstaller on each platform and bundle your app separately on each. You can do this from a single machine using virtualization.
The BadFileDescriptor
error and the consequently memory access violation are caused by the fact that the stdout
of applications in windowed mode is a fixed size buffer.
So, if you have are writing to stdout
, either with print
or sys.stdout
directly, after some time you'd see those errors.
You can fix this by:
stdout
logging
instead of printing to stdoutstdout
at the beginning of the execution of your application. This is the solution that requires less code to be changed, even though I think moving the debugging statements to logging
would be the better choice.To redirect stdout
you can use this kind of code:
import sys
import tempfile
sys.stdout = tempfile.TemporaryFile()
sys.stderr = tempfile.TemporaryFile()
Just before executing your program. You can use also some custom object to put the output in "log" files or whatever, the important thing is that the output should not fill the fixed size buffer.
For example you could do something like this to be able to take advantage of the logging
module without changing too much code:
import sys
import logging
debug_logger = logging.getLogger('debug')
debug_logger.write = debug_logger.debug #consider all prints as debug information
debug_logger.flush = lambda: None # this may be called when printing
#debug_logger.setLevel(logging.DEBUG) #activate debug logger output
sys.stdout = debug_logger
The downside of this approach is that print
executes more calls to stdout.write
for each line:
>>> print 'test'
DEBUG:debug:test
DEBUG:debug:
If you want you can probably avoid this kind of behaviour writing a real write
function that calls the_logger.debug
only with "full lines".
Anyway I think these kind of solution should only be temporary, and be used only before porting the print
s to calls to logging.debug
.
(Obviously the loggers should write to a file and not to stdout
to avoid the errors.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With