3

I'm trying to freeze with either cx_freeze or pyInstaller a TraitsUI program that makes use of Chaco, Traits, TraitsUI and to a lesser extent mayavi (could actually be taken out). I need this to run on mac, linux, ubuntu so am avoiding py2exe. I've intentionally uninstalled pyqt and pyside so that only the wx backend is available.

Using cx_freeze, I encountered and reported a bug, so pyInstaller seems to be getting me the furthest. It generated an .exe file, but when I run the file I get warnings and an error. To generate the .exe file I did:

pyinstaller --onefile --name=pameapp pamemain.py 
pyinstaller pameapp.exe

Upon running, the warnings are:

Warning: Unable to import the wx backend for pyface due to traceback: Traceback (most recent call last):
      File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/pyface.toolkit", line 45, in _init_toolkit
      File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/pyface.toolkit", line 31, in import_toolkit
    ImportError: No module named wx.init

Warning: Unable to import the qt4 backend for pyface due to traceback: Traceback (most recent call last):
      File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/pyface.toolkit", line 45, in _init_toolkit
      File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/pyface.toolkit", line 31, in import_toolkit
    ImportError: No module named init

Warning: Unable to import the null backend for pyface due to traceback: Traceback (most recent call last):
      File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/pyface.toolkit", line 45, in _init_toolkit
      File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/pyface.toolkit", line 31, in import_toolkit
    ImportError: No module named null.init

In addition, I get the following error:

Traceback (most recent call last):
  File "<string>", line 8, in <module>
  File "/home/glue/anaconda/envs/fibersim/lib/python2.7/site-packages/PyInstaller/loader/pyi_importers.py", line 270, in load_module
    exec(bytecode, module.__dict__)
  File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/traitsui.api", line 35, in <module>
  File "/home/glue/anaconda/envs/fibersim/lib/python2.7/site-packages/PyInstaller/loader/pyi_importers.py", line 270, in load_module
    exec(bytecode, module.__dict__)
  File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/traitsui.editors", line 22, in <module>
  File "/home/glue/anaconda/envs/fibersim/lib/python2.7/site-packages/PyInstaller/loader/pyi_importers.py", line 270, in load_module
    exec(bytecode, module.__dict__)
  File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/traitsui.editors.api", line 10, in <module>
  File "/home/glue/anaconda/envs/fibersim/lib/python2.7/site-packages/PyInstaller/loader/pyi_importers.py", line 270, in load_module
    exec(bytecode, module.__dict__)
  File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/traitsui.editors.code_editor", line 36, in <module>
  File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/traitsui.editors.code_editor", line 48, in ToolkitEditorFactory
  File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/traits.traits", line 487, in __call__
  File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/traits.traits", line 1191, in Color
  File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/traitsui.toolkit_traits", line 7, in ColorTrait
  File "/home/glue/Desktop/fibersim/pame/build/pameapp/out00-PYZ.pyz/traitsui.toolkit", line 137, in toolkit
traits.trait_errors.TraitError: Could not find any UI toolkit called 'null'

pyface probably has a lot of dynamic imports, so this must be a problem encountered by anyone who tries to freeze ETS. Is there a single fix to get this working?

Considering the older stuff floating around the web on success rates to freezing an ETS program, is it even worth further investment? To us, having people avoid configuring python for this application would be a huge plus.

Thanks.

Adam Hughes
  • 14,601
  • 12
  • 83
  • 122
  • For downvoting this question, it would be helpful to me if you could explain why so I avoid whatever the problem was in the future. – Adam Hughes Jan 22 '15 at 01:42
  • With cx_Freeze, I'd try adding `wx` to the list of packages included to see if that makes a difference. But I haven't tried freezing a traits UI application; it may not be practical. – Thomas K Jan 22 '15 at 19:14
  • Hey Thomas. I actually have been trying cx_freeze and I'm getting an error with collections library very similiar to a bug you had discussed before on bitbucket. Does this make any sense to you? https://bitbucket.org/anthony_tuininga/cx_freeze/issue/127/collectionssys-error#comment-15016355 If this were working, then I think the wx in packages would be fine. Similar to "collections.abc" I'm getting a "collections.sys" error – Adam Hughes Jan 22 '15 at 19:22
  • I've responded on Bitbucket. In short, I think that's only superficially similar to the bug I discussed before, but I hope we can resolve it anyway. – Thomas K Jan 22 '15 at 19:40
  • I've tried something similar before -- I think I looked at both py2exe and pyInstaller for mayavi programs with traitsui GUIs. I couldn't get them to work at all. Maybe it would be possible to get an embedded mayavi renderer in pure toolkit code (my preference woudl be Tk) and bypass traitsui -- I have tried to do this before for several reasons (that weren't this). I think it should be feasible in principle, but I haven't gotten around to doing it. If you did that, and then ported your GUI code, the cx_freeze might work. – aestrivex Jan 22 '15 at 23:47
  • I have no experience doing this, but I know Thomas Lecocq has had success in the past: http://www.geophysique.be/2011/08/01/pack-an-enthought-traits-app-inside-a-exe-using-py2exe-ets-4-0-edit/ I don't know if that blog post is sufficiently up-to-date to still work, and it appears he doesn't use chaco, but it might be a good starting point. – Warren Weckesser Jan 23 '15 at 18:29
  • Oh wait, I just reread the beginning of your question about avoiding py2exe. Sorry for the noise... – Warren Weckesser Jan 23 '15 at 18:31
  • No, it's fine. Thanks for sharing. Most of the hangups come back to dynamic imports, which is a problem in any package. If py2exe works, then it's better than nothing. – Adam Hughes Jan 23 '15 at 18:58
  • Interestingly, the error that someone in the comments of that post is encountering is pretty much the error I'm getting with cx_freeze about images not working. – Adam Hughes Jan 23 '15 at 19:00

1 Answers1

1

Pyface.toolkit you are using is using dynamic import:

def import_toolkit(tk):
    try:
        # Try and import the toolkit's pyface backend init module.
        be = 'pyface.ui.%s.' % tk
        __import__(be + 'init')
    except:
        raise
    return be

So pyinstaller is not able to detect this. Check with python -v b.py 2>&1 | grep imp what is the specific import and add hook file (hook-.py) with proper hiddenimports list.

However I've did some tests in local and I am not able to do working test schema with __import__. It's strange as I did some debugging and I found that hiddenimport is added but still not usable.

Dawid Gosławski
  • 2,028
  • 1
  • 18
  • 25