PyInstaller executable issue
ardoramor opened this issue · comments
After testing the application to work from source, I've built an executable:
pyinstaller.exe --onefile app.py
When I run the app.exe from the cmd, it prints the following error to the log:
Traceback (most recent call last):
File "", line 146, in
File "C:...\build\app\out00-PYZ.pyz\gooey.python_bindings.gooey_decorator", line 86, in inner
IOError: [Errno 2] No such file or directory: 'C:\Users...\AppData\Local\Temp_MEI108682\gooey_tmp\app.exe'
Does Gooey play well with PyInstaller or it hasn't been tested?
You're a bit of a pioneer :) I haven't dug into PyInstaller and what all Gooey needs in order to be packaged up nicely.
Try running it without --onefile. I know in the past there was an issue with PyInstaller that, for whatever reason, would cause it to throw an error whenever you packaged a python app that used multiprocessing
with --onefile
. I dunno if that's still the case, but it could be a good starting point for debugging.
(note: typing this at work.. so it's just a quick off the top of my head guess at one possible issue)
I'll hopefully dig into the issue soon.
I got the following output while compiling without --onefile:
Traceback (most recent call last):
File "", line 151, in
File "C:\Users...\Documents\Projects\app\build\App\out00-PYZ.pyz\gooey.python_bindings.gooey_decorator", line 86, in inner
IOError: [Errno 2] No such file or directory: 'C:\Users...\DOCUME1\PROJ1\Ap1\dist\Ap1\gooey_tmp\App.exe'
The following directory exists:
'C:\Users...\DOCUME1\PROJ1\Ap1\dist\Ap1
But gooey_tmp\App.exe does not exist.
Looking at PyInstaller's warning output, I noticed the following:
W: delayed import hack detected at line 0 - gooey.python_bindings.modules (C:\Python27\lib\site-packages\gooey-0.1.0-py2.7.egg\gooey\python_bindings\modules.pyc)
W: delayed import hack detected at line 0 - gooey.python_bindings.gooey_decorator (C:\Python27\lib\site-packages\gooey-0.1.0-py2.7.egg\gooey\python_bindings\gooey_decorator.pyc)
I can confirm this error as well, with perhaps a bit more traceback:
Traceback (most recent call last):
File "<string>", line 24, in <module>
File "Z:\...\build\build\test\out00-PYZ.pyz\gooey.python_bindings.gooey_decorator", line 96, in inner
File "Z:\...\build\build\test\out00-PYZ.pyz\gooey.gui.lang.i18n", line 41, in load
IOError: [Errno Language file not found. Make sure that your ] translation file is in the languages directory,
err:seh:setup_exception_record stack overflow 1568 bytes in thread 0009 eip 7bc4629f esp 00240d10 stack 0x240000-0x241000-0x340000
using the compile options
wine python pyinstaller/pyinstaller.py --hidden-import=gooey test.py
and the test file
import gooey
from gooey import GooeyParser
@gooey.Gooey()
def main():
parser = GooeyParser()
parser.add_argument('-i', widget='FileChooser')
args = parser.parse_args()
print "DONE"
if __name__ == '__main__':
main()
So, I tried messing around and compiling gooey. It did not work out but since there is an open issue i'll try to add in what i have.
I got passed the part where it complains about the language files (Thank you .spec file), with these files :
My test.py File
from gooey import Gooey
from gooey import GooeyParser
import argparse
@Gooey
def toto():
parser = GooeyParser()
parser.add_argument("toto")
print("After add_argument")
parser.parse_args()
toto()
print("Hello World!")
My test.spec File : (As a --onefile)
# -*- mode: python -*-
#Gooey_languages and gooey_images are used to fetch the files and solve the problem that was occuring preivously. (i.e : Language file not found)
gooey_languages = Tree('C:/Python27/Lib/site-packages/gooey/languages', prefix = 'gooey/languages')
gooey_images = Tree('C:/Python27/Lib/site-packages/gooey/images', prefix = 'gooey/images')
a = Analysis(['test.py'],
pathex=['c:\\Python27\\Scripts'],
hiddenimports=[],
hookspath=None,
runtime_hooks=None)
pyz = PYZ(a.pure)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
gooey_languages, # Add them in to collected files
gooey_images, # Same here.
name='test.exe',
debug=False,
strip=None,
upx=True,
console=True )
Commandline :
pyinstaller test.spec
Some warnings pop up, however since no reference to import issues are made when launched, i'm assuming they're uneventful.
C:\Python27\lib\site-packages\PyInstaller\hooks\hook-wx.lib.pubsub.core.py:11: RuntimeWarning: Parent module 'PyInstaller.hooks.hook-wx.lib.pubsub' not found while handling absolute import
import os
C:\Python27\lib\site-packages\PyInstaller\hooks\hook-wx.lib.pubsub.core.py:12: RuntimeWarning: Parent module 'PyInstaller.hooks.hook-wx.lib.pubsub' not found while handling absolute import
import PyInstaller.hooks.hookutils
C:\Python27\lib\site-packages\PyInstaller\hooks\hook-wx.lib.pubsub.core.py:14: RuntimeWarning: Parent module 'PyInstaller.hooks.hook-wx.lib.pubsub' not found while handling absolute import
from PyInstaller.hooks.hookutils import logger
And it outputs an executable. Yay! However when launched, it displays a Gooey window, allows you to enter the arguments, but once you hit start it outputs an error that always sticks to these lines :
File "c:\.....\appdata\temp\tmp_xxxxx.py", line 1
SyntaxError : Non-ASCII character '\x90' in file
c:\......\tmp_xxxxx,py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details.
So on I go to see what this says. And it is due to python believing all files are encoded in ascii since nothing else was specified. Very well. I meddled with site.py to set the default encoding to utf-8 and see if that would help. It did not. (Printing sys.getdefaultencoding()
returns utf-8
so i know it has been set and that the character in question is among the utf-8 set.)
As for adding the # -*- encoding : utf-8 -*-
to every file (gooey and all included) i didn't have the courage so i do not know if it could help.
As far as trying to do a directory build (and not a --onefile which is wht my spec file does) I could not figure out a way to bypass "missing python27.dll". Adding it to binaries did not work, it is present in both sys directories (32 and 64) so i must be doing something wrong on that side and thus cannot really test it that way.
But if the people who can manage a clean build without --onefile could throw in the lines that i added to fetch the language/image packs in the .spec file, it might solve the problem noted by @thoppe
@Roshgar, found the issue!
In gooey\python_bindings\config_generator.py
, change:
run_cmd = 'python {}'.format(source_path)
to
if hasattr(sys, 'frozen'):
run_cmd = source_path
else:
run_cmd = 'python {}'.format(source_path)
Gooey is trying to launch your file as if it were a python file, ie python myfile.exe
, leading to the weird encoding issues. Just tell it to launch as-is instead of prepending python
, and it works great.
Combining the solutions by @Roshgar and @daranguiz works great for me.
@daranguiz: Will you be creating a PR for this fix? I can do so instead if it's easier.
I'm also going to try to take a look at helping PyInstaller work out of the box with Gooey. They seem like a perfect combination.
I also have the issue where the language file are not found at runtime - @Roshgar 's method of editing the spec file does not help. The only difference I can see is that I'm using Linux, but I've adjusted the paths accordingly.
@iodbh There's a pull request by @Shura1oplot here ( #118) that says it has fixes for the numerous path issues. Do you wanna check out that branch and see if it fixes your problem?
Done. The fix works if I copy the languages and images directories into dist/gooey; but the files are not found if I add them to pyInstaller's collect files (via @Roshgar 's edits in the spec file). The new error message is more explicit :
IOError: cannot locate Gooey resources. It seems that the program was frozen, but resource files were not copied to directory of the executable file. Please copy `languages` and `images` folders from gooey module directory into `/home/user/projects/gooeytest/dist/gooey/` directory.
So the generated executable is now runnable if the directories are copied.
@tandreas : (
Arg... Alright, next task at the top of my TODO is to solve all these packaging woes!
Please try this #123.
Minor progress! I figured out how to make --onefile
play nice with the external resources! No more manual copying stuff. Turns out that part of the magic of onefile
is that it unpacks all of the resources into a temp directory on startup. See here: https://pythonhosted.org/PyInstaller/#run-time-operation
With that info, a quick update to @Shura1oplot's get_resource_handler
so that it grabs the _MEIPASS
directory when frozen and all seems to work nicely now.
I'm still facing missing import issues with multiprocessing
, but.. at least the non-code resources load!
@chriskiehl
Commit 660b0b0 breaks support of cx_freeze
as it does not set sys._MEIPASS
. Both freezers should work with PR #123.
@Shura1oplot Doh! I hadn't looked at that pull. I'll revert f0c3771 and merge in #123.
I think we can almost call this issue officially solved! I can package using both PyInstaller and cxFreeze on both Windows and Linux. Wiki entry on the topic is in progress (On my win8 machine, I'm needing a small hack to force stdout
to flush when using pyinstaller).
The last piece of this is just sanity checking that it packages okie-dokie on OSX. Once that's confirmed, this issue is done!
@chriskiehl Has OSX packaging been confirmed? If so, are there special instructions I need to follow? I can't get it to work for me.
I tried to build a simple demo using pyinstaller. It compiles without errors, and the UI entry form comes up when I run the .exe, but nothing happens when I click the start button. No error message. The window just stays as is (except the start button does "depress" when it is clicked)
The script works if not compiled.
Environment: Windows 7. Python 2.7, 64 bit. Gooey 0.9.2.3, pyinstaller 3.1.1
I tried the spec file as detailed under "Packaging Gooey as a Distributable Application", and the one at https://github.com/chriskiehl/Gooey/files/29568/build.spec.txt. (They are different by a couple lines. Same result for both)
If I add the stdout fix lines, I get fatal error: ....exe returned -1
If no entry is made for a required argument, then the expected error popup does come up after I click start.
Any thoughts on what's wrong, or suggestions to try, would be a huge help. Thank you. - Chris
I tried to build a simple demo using pyinstaller. It compiles without errors, and the UI entry form comes up when I run the .exe, but nothing happens when I click the start button. No error message. The window just stays as is (except the start button does "depress" when it is clicked)
The script works if not compiled.
^ Im having the EXACT same problem, its been driving me nuts....would love to find a solution to get rid of the error or the console window. In addition, I had to compile with pyinstaller 3.1 instead of 3.2.
My own module uses subprocess and I ran into the same issue. However, a strange thing happens (which is unrelated) where if I issue subprocess.call when frozen, a console comes up for every call instance. My program works as intended though.
Actually I fixed my own subprocess issue by following the comment here:
https://groups.google.com/d/msg/pyinstaller/-4Fdy7suh0U/0o9Yqa78zCEJ
Turns out you just need to addd a startupinfo object to your subprocess call.
It's also documented here on the PyInstaller website: https://github.com/pyinstaller/pyinstaller/wiki/Recipe-subprocess
So after all this, my frozen Gooey executable works perfectly. Thanks so much for this project!
"but nothing happens when I click the start button"
I'm also having this issue, anyone have any ideas?
I managed to track this a bit further.
It seems ProcessController.run hits an exception when calling subprocess.Popen, if the --noconsole option is supplied when running pyinstaller.
http://stackoverflow.com/questions/33020644/python-subprocess-popen-with-pyinstaller
It works for me if I enable console in the build.spec
console=True,
Of course, that enables a big console window in the background :( but it's a workaround
To use cx_freeze
with Gooey on OSX, I had to specify the language/image resources to include:
import os
import gooey
from cx_Freeze import setup, Executable
def get_resources():
target_prefix = 'gooey'
source_dir = os.path.dirname(gooey.__file__)
subdirs = ['languages', 'images']
includes = []
for directory in subdirs:
path = os.path.join(source_dir, directory)
for file in os.listdir(path):
file_path = os.path.join(path, file)
relative_path = os.path.join(target_prefix, directory, file)
includes.append((file_path, relative_path))
return includes
setup(
name="my_gooey_app",
version="0.1",
description="My Gooey App",
options={"build_exe": {'include_files': get_resources()}},
executables=[
Executable("my_gooey_app.py", base=base),
]
)
I also to make sure to use a python version compiled with support for GUI applications (--enable-shared
or --enable-framework
). I use pyenv, so I had to follow these instructions.
I guess this confirms it for OSX.