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
How can I pyinstaller my script with pyface? #350
Comments
Any fix for this? |
No - we don't deploy apps at Enthought using PyInstaller or similar tools, so this hasn't been a priority. The problem that you are experiencing is around the use of entry points to set up the toolkit. You might be able to work around this by replacing the entire
Adjust appropriately is you are using wxPython This hard-codes the toolkit import, rather than delegating it to configuration. You'll need to do something like this in TraitsUI as well, most likely. |
So I edited the toolkit.py file as mentioned above, I am now getting this error |
You have a |
Additionally, I think you might need to tell PyInstaller to bundle everything in |
@corranwebster Yes, the executable is a GUI made on tkinter that has a visualize button which opens up a mayavi window. It works fine when I just run the main script. This problem only pops up when I run the executable.
Do I add it to hidden imports? |
Has anyone been able to get this to work? I've been trying for days to no avail, and I'd really like to not have to get rid of traitsui... |
@wlievens what is the failure mode you see when you try to use pyinstaller? |
Thanks for the reply. When I use pyface "out of the box" as a dependency, and I run the generated executable I get the following runtime exception:
I then applied the suggestion above at #350 (comment) and replaced the toolkit.py code with the more "build time" import. When I build the new executable and run it, I get the following error:
I have tried further hacking the various toolkit files and their imports but never got anywhere... I really like traitsui so I'd love to keep using it, but the exe build is also a hard requirement. |
Does anyone have any ideas on how to proceed? |
@wlievens does the discussion in enthought/traitsui#458 help? |
That discussion is a big mess, mixing tips for pyinstaller and cx_freeze, but I tried a few suggestions from there, i.e. setting the env vars and forcing the pyface.api import early in my main file. So I restarted my efforts and undid the changes suggested here: And then in my own main file I started off with this: enthought/traitsui#458 (comment) I then got this error:
So I went to look in that file and added some debug prints (I don't know how to use the built-in logger). In the
Now of course I do have Since the tip from #3050 contained turning on ETS_DEBUG, I now get this error:
here: Figured I'd report that here, but I can turn off ETS_DEBUG for now of course. I ran again with debug off and now see this familiar error again:
So I'm stuck again I suppose. |
@wlievens im assuming you're working with pyface 7.3.0 (the latest release). If I understand you correctly, the exception is being raised because the return in this else statement doesn't happen - Lines 174 to 177 in ded5d29
getattr(module, oname, None) returns None . I can't imagine why that would be happening.
Also, are you doing the following -
To give you a better understanding of the internals, pyface is an abstraction layer and multiple toolkit-specific implementations sit behind the abstraction i.e. the qt implementation and the wx implementation. For this reason, pyface dynamically chooses which toolkit to use depending on the packages installed in the environment or depending on the existence of specific environment variables. That determination happens by looking at the package metadata - which if im not wrong is stored in the Without those |
Hi, thanks for the additional info. I did indeed see that and tried something but I'm not sure I did it right. I don't actually see the
|
@wlievens |
The dist-info dirs contain the
I'm on Windows 10. I use poetry to manage dependencies and virtual environment. Python is 3.8.6 (64 bit). The pyinstaller version is 4.2, pyface is 7.3.0 and traitsui is 7.1.1. |
Can you provide the script or spec file that you are using to setup/use pyinstaller? I personally don't have a lot of experience using pyinstaller but I can try to spend sometime this weekend to see what's going wrong. I can't promise a solution though. |
Thanks for looking into it. I'm continuing the investigation myself, too: I just added `pyface.ui.qt4.clipboard``` to hiddenimports and that seems to move the error to the next problem ...
|
I wrote this at the start of my .spec file
And now I no longer get pyface-related errors! So I think it's resolved by doing that. I now get similar errors about dynamically-loaded qt5 backends from a different dependency (vispy) :-D But maybe I can solve it the same way... |
@corranwebster gave me a brief introduction to how packages like pyinstaller work i.e. they include modules in the installer only if they are imported explicitly. In the case of pyface AND traitsui, the packages dynamically import from the qt or wx backends depending on which toolkit is installed. So, for pyinstaller (or other similar tools) to work correctly, you will need to explicitly specify the pyface/traitsui submodules for the toolkit you use i.e. @wlievens thanks for getting back to us with what worked. We'll try to consolidate this information and document it for future users. |
I tried specifying |
Yeah, that sounds about right. Instead of adding modules from pyface that the pyinstaller needs, I would recommend including all of pyface and then slowly removing modules that you think are irrelevant to see what happens. I don't know if that would make the process easier or harder. Again, I don't have much experience actually using pyinstaller. |
I'm in the middle of a big fight with pyinstaller now over some unrelated issue (it cannot find some standard python modules when running as single executable ...), but if I get that resolved I will try to narrow down the acceptable configuration for pyface, and I'll report back here :-) |
@wlievens Hi can you solve mayavi to use pyinstaller? If you solve ,please tell me the way to solve thanks. |
What I ended up doing I think to get traitsui & pyface working is this in my
It essentially just lists all the packages and all the subpackages. Somehow this helped, I think. |
I mentioned the following in an earlier comment.
I haven't tested this but here again, I presume the solution will be to explicitly add all of |
Your comment is likely the reason why I came up with that solution, I just don't recall the specifics since it's ~7 months ago. |
@wlievens Thanks for you reply, I will try your advise. |
I spent a few hours today and think I have a simple way that seems to work with PyInstaller 5 (may work with earlier versions, but that's what I have installed). The issues that people have are threefold:
PyInstaller has utility functions for each of these cases: The following code can be used as a hook (eg.
If using TraitsUI, you would need to write a very similar hook for TraitsUI. If using Enable or Chaco, you would need similar for Kiva and Enable (I haven't yet tried any of these). These are not optimized - these will include wxPython backend files even if you are only using Qt, for example - but that shouldn't matter since the size of Pyface is small compared to Qt or Wx. Having done this research, and since the code is not large, I'll likely add the PyInstaller hooks to Pyface in the next minor release, after which it will hopefully Just Work. |
me too, any suggestion is appreciated |
Please try the instructions and code here: https://github.com/jonathanrocher/ets_tutorial/tree/master/stage8.2_packaging_pyinstaller |
I want to package my script with mayavi, everything runs well on python, but after using pyinstaller to package my script, I got "No pyface.toolkits plugin found for toolkit wx". More realted information:
https://stackoverflow.com/questions/50337382/creating-standalone-exe-using-pyinstaller-with-mayavi-import
https://stackoverflow.com/questions/51236026/how-to-use-pyinstaller-or-cx-freeze-to-package-a-python-script-containing-traits
The text was updated successfully, but these errors were encountered: