Be careful with Python asyncio.wait

Recently, I stumbled upon an annoying issue with Python's asyncio module, that is asyncio.wait terminating your program with "success" status when error occurs.

What is abnormal here?

Normally, when exception occurs, and you don't want to recover from it (with try... except), your program will exit as failure (non-zero exit code). However, if you have this code:


Flask extension and isinstance conflict

The way of importing Flask extensions is so annoying:

from import Bar

It is annoying because most of the Python IDEs (Komodo and PyCharm) cannot parse it to provide code navigation or autocompletion.

Another way to make Python web app do concurrency

I'm developing a Python web app that emulate WifiDog for remote demo purpose. It is not just a normal web app because it has to run 2 jobs as the same time:

  • Run as a webserver, to redirect user visit to the URL of WifiDog's remote Auth Server.

  • Periodically report system state to Auth Server as a normal HTTP request.

Make the first one is easy. The web part actually don't have much thing to do. It only builds some URL and redirect user to. A small script based on Bootle is enough. What make me concern is the second requirement. Normally, when I build a website on Django or Flask and I need the web do some periodic task, I just use Celery. But here I don't want to use Celery because Celery require me to run another command (celery) beside the main one (which is to launch my web app). Using Celery also means that I have to install more programs like RabbitMQ. It is a waste for just a small, simple web app.

Flask-SQLAlchemy consuming 100% CPU with multi-thread WSGI server.

These days I has been taking my hairs with a critical issue on my web app, when it eats up to 100% CPU of my VPS.

My web app plays role as an authentication server for splash-protected Wifi network. When people want to use the network, the router (with WifiDog installed) will drive them to a login page first, requiring them to authenticate to get Internet access. With this usage, I don't expect the server to get too many guests. That's why I chose to build it with Flask. For database utilization, I pick SQLAlchemy for safety and because at that time, none of others supports Python3.

The website runs smoothly until one recent day we realized that it took 100% CPU and made the server irresponsive. I tried many ways, including rollbacking the code to old revisions, downgrading the libraries but none helps. At first I ran with CherryPy as WSGI server, then I tried switching to Waitress. No help. When I ran with Flask's built-in Flask server, I noticed that the CPU usage no longer increased to 100%, but in other hand, the web kept hanging. The browser could connect and make HTTP request, but got no response.

After many days trying and testing as well as doing optimize code which exploits database, I try the last option: switching to Gunicorn. Surprisingly, this helps! Though I don't know how Gunicorn fix the problem, or where is the defect in my code, I can assert that it is not because "Gunicorn is superior to others". The difference between Gunicorn and the other forementioned is that one is multi-process type and one is multi-thread (CherryPy, Waitress). My use, my setup of SQLAlchemy/PostgreSQL is somehow compatible with multi-process server rather than multi-thread. But by which manner, I don't know. There are many of setup of Flask+SQLAlchemy+CherryPy out there but no one complaints about 100% CPU issue. It proves that the issue is not CherryPy/Waitress's fault.

Tạo nhanh web/FTP server với Python

Khi cần chia sẻ file qua mạng nội bộ, tôi thường nghĩ đến việc chạy 1 web server hay FTP server, nhưng lại ngại cài những phần mềm chuyên dụng như Apache, ProFTP vì tôi chỉ muốn chạy server trong 1 khoảng thời gian ngắn, chỉ phục vụ tải file cho một thư mục nhất định và không muốn cấu hình username/password để login.

Chẳng hạn, nếu cài webserver chuyên dụng như Apache, Nginx thì thường thư mục gốc sẽ là /var/wwww/, nếu muốn chia sẻ file từ 1 thư mục bất kì thì phải tạo symlink vô đây, và phải gõ password để lên sudo. Nếu cài 1 FTP server chuyên dụng như ProFTP thì từ client truy cập vô, luôn đụng phải thư mục root và phải đăng nhập username, password.

Thật mừng là Python có những thư viện đáp ứng rất tốt nhu cầu. Chẳng hạn tôi muốn chia sẻ file từ thư mục /home/hongquan/Documents, tôi chỉ việc vào thư mục đó và chạy: