5

I am building an API that uses Waitress, Flask, and Flask_SocketIO in Windows. Everything works fine from the command line, but when I try to bundle my API into an .exe using cx_Freeze and then run it, I get the error:

ValueError: Invalid async_mode specified

The only thing I've been able to find about this issue is a python-socketio github thread. There are a ton of good suggestions in that thread to try in order to fix this issue, but I've tried each and every thing but still have the same result.

I suspect I have a missing module, but I have no idea how to find out specifically which module is missing. Does anyone have any suggestions of things to try? Even if it doesn't directly fix my problem, knowing how to drill into the stack trace to find the missing module would be helpful.

jpeg
  • 2,372
  • 4
  • 18
  • 31
Brian
  • 5,826
  • 11
  • 60
  • 82
  • What modules did you include? – Miguel Grinberg Jan 11 '19 at 19:23
  • sys, datetime, flask, flask_socketio, jwt, ConfigParser, pyodbc & uuid – Brian Jan 11 '19 at 21:05
  • 1
    That's not the problem, you need to import specific sub-modules of the python-engineio package for things to work. The people who commented on the thread you linked explained what they did to make things work. – Miguel Grinberg Jan 12 '19 at 18:15
  • I just went back through that thread and tried a few different async_modes and including their respective modules into the cx_freeze package but kept getting the same error. – Brian Jan 17 '19 at 03:46
  • The location of the async modules have changed, did you adapt the import names to the current locations? – Miguel Grinberg Jan 17 '19 at 09:36

3 Answers3

7

This troubled me a lot while using pyInstaller. I tried adding many different modules to hidden imports, but realized later that you just need to mention below in your py file:

from engineio.async_drivers import gevent

Hope this works for cx_Freeze as well.

jpeg
  • 2,372
  • 4
  • 18
  • 31
Mahesh
  • 982
  • 8
  • 20
3

EDIT:

Try to add engineio, socketio, flask_socketio, threading, time, queue to the packages list of the build_exe options passed to the setup call in your setup script:

...

packages = []  # Add here the list of packages you have already included
packages += ['engineio', 'socketio', 'flask_socketio', 'threading', 'time', 'queue']

...

setup(...,
      options={'build_exe': {...,
                             'packages'=packages}})

As posted by espretto in the thread you linked:

apparently engineio uses the importlib module to dynamically import whichever module corresponds to the chosen async_mode

cx_Freeze does not interpret this code and thus does not know that sub-modules of engineio need to be included, you need to tell it.

engineio.async_drivers.threading imports threading, time and queue, but cx_Freeze probably won't see that because engineio.async_drivers.threading is imported dynamically.

If queue does not work, replace by Queue.

You might still need to add further packages to the packages list, such as eventlet, gevent, uwsgi, six, urllib3, ...

Please post the full stack trace of the error message you get. Seeing where the error happens and looking into the source code of engineio might help to find the missing package.

jpeg
  • 2,372
  • 4
  • 18
  • 31
  • I tried explicitly setting async_mode to 'threading' and importing async_threading and got the same error – Brian Jan 17 '19 at 03:44
  • @brian have you tried to add `engineio` and maybe `socketio` and `flask_socketio` to the `packages` list in your setup script? Do you still get the same error? At least `engineio` does some dynamical import which is probably not recognized by `cx_Freeze`, importing `async_threading` only might not be enough. – jpeg Jan 23 '19 at 07:05
  • @brian I've edited my answer with further suggestions. – jpeg Jan 23 '19 at 08:07
1

For eventlet install it first using:

pip install eventlet

PSN
  • 2,326
  • 3
  • 27
  • 52