I am using Flask-SocketIO, uWSGI with Gevent, and Nginx for the development of the WebSocket project and dockerizing this app as well. The simple run of my app is good but when I add uWSGI with Gevent, and Nginx it gives me an error which is TypeError: 'module' object is not callable. I searched the internet but nothing get helpful material. What should I do to solve this problem? My flask project structure is:
vsoTS
│
├───app
│ │ views.py
│ │ __init__.py
│ ├───static
│ │ └───js
│ │ │ application.js
│ │ ├───templates
│ │ │ index.html
├───env
│ .dockerignore
│ app.ini
│ Dockerfile
│ requirements.txt
│ run.py
run.py
from gevent import monkey
monkey.patch_all()
from app import app
from app import socketio
print(type(socketio))
sock = socketio
if __name__ == "__main__":
sock.run(host='0.0.0.0', port = 8084)
init.py
from flask import Flask
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app ,logger=True, engineio_logger=True)
from app import views
nginx.conf
server{
location /vsoTS {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://0.0.0.0:8084;
}
location /socket.io {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://0.0.0.0:8084/socket.io;
}
}
uWSGI configuration resides in app.ini
[uwsgi]
gevent-monkey-patch = true
wsgi-file = run.py
callable = app
processes = 4
threads = 2
master = true
chmod-socket = 660
vacuum = true
mount = /=run.py
manage-script-name = true
die-on-term = true
py-call-osafterfork = true
need-app = true
enable-threads = true
strict = true
buffer-size=32768
gevent = 1000
http-websockets = true
http-socket = 0.0.0.0:8084
single-interpreter = true
After running the flask app in a Docker container, it shows me the TypeError: 'module' object is not callable detailed logs are given below.
vsots | [uWSGI] getting INI configuration from app.ini
vsots | *** Starting uWSGI 2.0.18 (64bit) on [Fri Jul 16 00:01:07 2021] ***
vsots | compiled with version: 8.3.0 on 16 July 2021 00:00:39
vsots | os: Linux-5.4.72-microsoft-standard-WSL2 #1 SMP Wed Oct 28 23:40:43 UTC 2020
vsots | nodename: e1f246977cb5
vsots | machine: x86_64
vsots | clock source: unix
vsots | pcre jit disabled
vsots | detected number of CPU cores: 8
vsots | current working directory: /app
vsots | detected binary path: /usr/local/bin/uwsgi
vsots | uWSGI running as root, you can use --uid/--gid/--chroot options
vsots | *** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
vsots | your memory page size is 4096 bytes
vsots | detected max file descriptor number: 1048576
vsots | - async cores set to 1000 - fd table size: 1048576
vsots | lock engine: pthread robust mutexes
vsots | thunder lock: disabled (you can enable it with --thunder-lock)
vsots | uwsgi socket 0 bound to TCP address 0.0.0.0:8084 fd 3
vsots | uWSGI running as root, you can use --uid/--gid/--chroot options
vsots | *** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
vsots | Python version: 3.9.5 (default, Jun 23 2021, 15:01:51) [GCC 8.3.0]
vsots | Python main interpreter initialized at 0x5627d11d8810
vsots | uWSGI running as root, you can use --uid/--gid/--chroot options
vsots | *** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
vsots | python threads support enabled
vsots | your server socket listen backlog is limited to 100 connections
vsots | your mercy for graceful operations on workers is 60 seconds
vsots | mapped 703600 bytes (687 KB) for 8 cores
vsots | *** Operational MODE: preforking+threaded ***
vsots | Server initialized for eventlet.
vsots | Server initialized for eventlet.
vsots | <class 'flask_socketio.SocketIO'>
vsots | WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x5627d11d8810 pid: 1 (default app)
vsots | mounting run.py on /
vsots | <class 'flask_socketio.SocketIO'>
vsots | WSGI app 1 (mountpoint='/') ready in 0 seconds on interpreter 0x5627d11d8810 pid: 1
vsots | uWSGI running as root, you can use --uid/--gid/--chroot options
vsots | *** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
vsots | spawned uWSGI master process (pid: 1)
vsots | spawned uWSGI worker 1 (pid: 8, cores: 2)
vsots | spawned uWSGI worker 2 (pid: 9, cores: 2)
vsots | *** running gevent loop engine [addr:0x5627cf7f1cf0] ***
vsots | TypeError: 'module' object is not callable
vsots | TypeError: 'module' object is not callable
vsots | TypeError: 'module' object is not callable
vsots | spawned uWSGI worker 3 (pid: 10, cores: 2)
vsots | TypeError: 'module' object is not callable
vsots | TypeError: 'module' object is not callable
vsots | TypeError: 'module' object is not callable
vsots | spawned uWSGI worker 4 (pid: 11, cores: 2)
vsots | TypeError: 'module' object is not callable
vsots | TypeError: 'module' object is not callable
vsots | TypeError: 'module' object is not callable
vsots | TypeError: 'module' object is not callable
vsots | TypeError: 'module' object is not callable
vsots | TypeError: 'module' object is not callable
The first problem with my code was, I was importing
SocketIOfrom the originalflask_socketiolibrary and I also imported this in the__init__.pyfile of my app folder. on the other hand, I was importing socketio object from__init__.pyin therun.pyfile so there was a conflict of importing the objects from libraries, that's why TypeError: 'module' object is not callable error raised. Solution to my problem is given bellow.init.py
views.py
run.py
this is the
flask-socketioapp. to run app I usedgunicorninstead ofuWSGIon top of this which actually working as a bridge betweennginxandflask_socketioapps, both are running in different docker containers. gunicorn configuration for flask socketio app in a docker container is,The second problem with my code was in the configuration of nginx which is running in a separate docker container. I was proxy passing nginx to http socket address which was in my case
proxy_pass http://0.0.0.0:8084;andproxy_pass http://0.0.0.0:8084/socket.io;these passes was wrong. The correct configuration for this is proxy pass to actually docker container in which your flask socketio resides and on top of it gunicorn is used to run this app. in my case, docker containervsotsrunning on the port of8084. nginx configuration for socket app running in docker container is,Screenshot of my flask socket app running in docker container through nginx.