Multiple Flask apps in Windows Apache

530 views
Skip to first unread message

Daniel Gutiérrez

unread,
Sep 15, 2020, 8:19:04 AM9/15/20
to modwsgi

Hi, I want to host multiple Flask apps through Apache in the same Windows 10 server. I want each app to be running on different ports. I figured that each app must have its own Python configuration, otherwise Apache will only run one of the two web apps. I have seen that in Linux you are supposed to use WSGIDaemonProcess command in the VirtualHost file, but this does not work on Windows.

I tried using

import sys
activate_this = 'C:/CRM4_Flask/venv/Scripts/activate_this.py'
with open(activate_this) as file_:
exec(file_.read(), dict(__file__=activate_this))

#Expand Python classes path with your app’s path
# The string inputted as the parameter corresponds to the web app's path in C
sys.path.insert(0, "C:/CRM4_Flask")

from run import app as application

in my run.wsgi file for each app. However, I always get the following error:

Fatal Python error: initfsencoding: unable to load the file system codec
ModuleNotFoundError: No module named 'encodings'

What alternative do I have instead of using WSGIDaemonProcess, given that it does not work on Windows? Im using Apache 2.4, Python 3.7.7, Windows 10 and mod_wsgi 4.7.1

My VirtualHost configuration for one of the web apps I want to host is:


<VirtualHost *:80>

    ServerName localhost:80
    ServerAlias localhost:80
    ServerAdmin ad...@email.com

    DocumentRoot c:/CRM4_Flask

    <Directory c:/CRM4_Flask>
        Require all granted
    </Directory>

    WSGIScriptAlias / c:/CRM4_Flask/run.wsgi
    WSGIApplicationGroup %{GLOBAL}

    <Directory c:/CRM4_Flask>
        Options +FollowSymLinks
        Require all granted
    </Directory>

    ErrorLog "logs/crm4-error.log" 
    CustomLog "logs/crm4-access.log" common 

</VirtualHost>

In the httpd.conf I added the following lines:

LoadFile "c:/users/administrator/appdata/local/programs/python/python37/python37.dll"
LoadModule wsgi_module "c:/crm4_flask/venv/lib/site-packages/mod_wsgi/server/mod_wsgi.cp37-win_amd64.pyd"
#WSGIPythonHome "c:/crm4_flask/venv"

I commented WSGIPythonHome because in theory I need Apache to load two versions of Python, not only one.

Please let me know if I am doing something wrong or if I should try something else.

Thanks guys!




Graham Dumpleton

unread,
Sep 15, 2020, 8:31:10 AM9/15/20
to mod...@googlegroups.com


> On 15 Sep 2020, at 10:17 pm, Daniel Gutiérrez <dguti...@artaviaconsultoria.com> wrote:
>
>
> Hi, I want to host multiple Flask apps through Apache in the same Windows 10 server. I want each app to be running on different ports. I figured that each app must have its own Python configuration, otherwise Apache will only run one of the two web apps. I have seen that in Linux you are supposed to use WSGIDaemonProcess command in the VirtualHost file, but this does not work on Windows.
>
> I tried using
>
> import sys
> activate_this = 'C:/CRM4_Flask/venv/Scripts/activate_this.py'
> with open(activate_this) as file_:
> exec(file_.read(), dict(__file__=activate_this))
>
> #Expand Python classes path with your app’s path
> # The string inputted as the parameter corresponds to the web app's path in C
> sys.path.insert(0, "C:/CRM4_Flask")
>
> from run import app as application
>
> in my run.wsgi file for each app. However, I always get the following error:
>
> Fatal Python error: initfsencoding: unable to load the file system codec
> ModuleNotFoundError: No module named 'encodings'

This error has nothing to do with use of activate_this files and indicates that the Python libraries can't find your Python installation for some reason.

Still set WSGIPythonHome, but set it to where the main Python installation is located (not the virtual environment).

This should be the value of sys.prefix, or at least I hope so as I can't remember what Windows uses for the main Python installation.

> What alternative do I have instead of using WSGIDaemonProcess, given that it does not work on Windows? Im using Apache 2.4, Python 3.7.7, Windows 10 and mod_wsgi 4.7.1
>
> My VirtualHost configuration for one of the web apps I want to host is:
>
>
> <VirtualHost *:80>
>
> ServerName localhost:80
> ServerAlias localhost:80
> ServerAdmin ad...@email.com
>
> DocumentRoot c:/CRM4_Flask
>
> <Directory c:/CRM4_Flask>
> Require all granted
> </Directory>
>
> WSGIScriptAlias / c:/CRM4_Flask/run.wsgi
> WSGIApplicationGroup %{GLOBAL}

Provided that both your WSGI applications only use third party modules that work fine in sub interpreters, all you need to do is NOT set WSGIApplicationGroup.

So long as you don't set it, each WSGI application will run in a separate Python sub interpreter of the same process and in the main shouldn't interfere with each other, or at least to the extent that sub interpreters separate things.

This is because sub interpreters are used by default, where the name of the sub interpreter is based on the name of the virtual host, the port, and the mount point of the WSGI application. So long as your two virtual hosts are on different ports (except for 80/443 which are still treated as one), they should be separate.

If you are using Python packages such as numpy then you will have a problem though. This is because numpy and thus a lot of the scientific packages for Python don't work in sub interpreters. Usually with those you would force the use of the main Python interpreter context. This is fine on Linux where have multiple apps which all need that to be done, as you can delegate each to separate daemon process groups. On Windows though you would be out of luck, as only one could be delegated to the main Python interpreter.

The directive which delegates the WGSI application to the main interpreter is:

WSGIApplicationGroup %{GLOBAL}

which is why I am asking you not to set it, cause right now you are telling both to run in the main interpreter, so they will conflict.

Graham

Daniel Gutiérrez

unread,
Sep 15, 2020, 8:56:43 AM9/15/20
to modwsgi
Hi Graham,

Thank you for your quick response.

Ok, so I did a couple things:


1) Set WSGIPythonHome = "c:/users/administrator/appdata/local/programs/python/python37" in httpd.conf

2) Removed WSGIApplicationGroup %{GLOBAL} from VirtualHost configuration

Once I did that, I actually did not get the "encodings" error I was getting before. However, I got an Internal Server Error. I assumed this happened because the main Python interpreter didn't have the necessary modules that the virtualenv did have (thus, I pip installed them). 

Now I am getting the following error:

File "C:\\CRM4_Flask\\venv\\Lib\\site-packages\\uuid.py", line 138\r, referer: http://172.16.3.120/
[Tue Sep 15 06:54:38.538334 2020] [wsgi:error] [pid 6244:tid 1228] [client ]     if not 0 <= time_low < 1<<32L:
SyntaxError: invalid syntax\r, referer: http://ip/

This is apparently happening in uuid module, which in theory has nothing to do with my app. I guess it is a built in module or something. What can i do?

Graham Dumpleton

unread,
Sep 15, 2020, 5:04:21 PM9/15/20
to mod...@googlegroups.com

On 15 Sep 2020, at 10:56 pm, Daniel Gutiérrez <dguti...@artaviaconsultoria.com> wrote:

Hi Graham,

Thank you for your quick response.

Ok, so I did a couple things:


1) Set WSGIPythonHome = "c:/users/administrator/appdata/local/programs/python/python37" in httpd.conf

2) Removed WSGIApplicationGroup %{GLOBAL} from VirtualHost configuration

Once I did that, I actually did not get the "encodings" error I was getting before. However, I got an Internal Server Error. I assumed this happened because the main Python interpreter didn't have the necessary modules that the virtualenv did have (thus, I pip installed them).

You should not need to install the modules in the system Python installation so long as the activate_this code was in the correct spot within the WSGI script file, and that it actually works on Windows (I can't remember if it does or not).

Make sure that the activate_this code is before all other imports except for 'import sys'.

After the activate_this code and before doing anything else, add:

    print(sys.path)

and check Apache logs to see what it was set to for each application. What do you see?

What Python distribution are you trying to use? The standard one from Python software foundation, or the Anaconda distribution?

Graham

Now I am getting the following error:

File "C:\\CRM4_Flask\\venv\\Lib\\site-packages\\uuid.py", line 138\r, referer: http://172.16.3.120/
[Tue Sep 15 06:54:38.538334 2020] [wsgi:error] [pid 6244:tid 1228] [client ]     if not 0 <= time_low < 1<<32L:
SyntaxError: invalid syntax\r, referer: http://ip/

This is apparently happening in uuid module, which in theory has nothing to do with my app. I guess it is a built in module or something. What can i do?

This sorts of suggests that the mod_wsgi might be compiled for a different Python version. Can't think what else could cause it.

When you install mod_wsgi, make sure you are using:

    pip install -U --no-cache-dir mod_wsgi

so that any prior build of the package is installed.

-- 
You received this message because you are subscribed to the Google Groups "modwsgi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to modwsgi+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/modwsgi/bc1efda6-62b0-444c-8981-a9eb47ff7bd2n%40googlegroups.com.

Daniel Gutiérrez

unread,
Sep 15, 2020, 6:19:31 PM9/15/20
to mod...@googlegroups.com
I solved my problem in a different way.. I downloaded Apache for a 2nd time, hence creating two instances of Apache24. The second instance I named it Apache24_2

So what I did is:

1) Download Apache24 from https://www.apachelounge.com/download/

2) Rename the downloaded folder to Apache24_2. Extract that folder to the same directory where Apache24 (original instance of Apache) is. In my case, both Apache instances would be in "C:/". 

3) Open Apache24_2's httpd.conf and httpd-vhosts.conf files. In httpd.conf I modified the following:

Define SRVROOT "c:/Apache24_2"

#ServerRoot "${SRVROOT}"
ServerRoot "c:/Apache24_2"

# Modified the port. I left Apache24 (original Apache instance) with port 80. I set Apache24_2's port to port 5000.
# Listen 80
Listen 5000

4) In Apache24_2's httpd.conf file, include virtual host and paste my mod_wsgi configuration:

Include conf/extra/httpd-vhosts.conf

LoadFile "c:/users/administrator/appdata/local/programs/python/python37/python37.dll"
LoadModule wsgi_module "c:/app2/venv/lib/site-packages/mod_wsgi/server/mod_wsgi.cp37-win_amd64.pyd"
WSGIPythonHome "c:/app2/venv"

5) Set Apach24 (original instance) httpd.conf with app1's corresponding mod_wsgi installation:

Listen 80

Include conf/extra/httpd-vhosts.conf

LoadFile "c:/users/administrator/appdata/local/programs/python/python37/python37.dll"
LoadModule wsgi_module "c:/app1/venv/lib/site-packages/mod_wsgi/server/mod_wsgi.cp37-win_amd64.pyd"
WSGIPythonHome "c:/app1/venv"

6) Set the following virtual host for Apache24 (original):

<VirtualHost *:80>

    ServerName ip:80
    ServerAlias ip:80
    ServerAdmin em...@email.com

    DocumentRoot c:/app1

    <Directory c:/app1>
        Require all granted
    </Directory>

    WSGIScriptAlias / c:/app1/run.wsgi
    WSGIApplicationGroup %{GLOBAL}

    <Directory c:/app1>

        Options +FollowSymLinks
        Require all granted
    </Directory>

    ErrorLog "logs/app1-error.log" 
    CustomLog "logs/app1-access.log" common

</VirtualHost>

7) Set the following virtual host for Apache24_2 (second instance):

<VirtualHost *:5000>

    ServerName ip:5000
    ServerAlias ip:5000
    ServerAdmin em...@email.com

    DocumentRoot c:/app2

    <Directory c:/app2>
        Require all granted
    </Directory>

    WSGIScriptAlias / c:/app2/run.wsgi
    WSGIApplicationGroup %{GLOBAL}

    <Directory c:/app2>

        Options +FollowSymLinks
        Require all granted
    </Directory>

    ErrorLog "logs/app2-error.log" 
    CustomLog "logs/app2-access.log" common

</VirtualHost>
6) Once both Apaches are configured respectively, stop Apache24's service (if running).

7)  In CMD go to C:/Apache24_2/bin. In CMD enter httpd.exe -k install -n "Apache24_2" -f "C:/Apache24_2/conf/httpd.conf"

8) Go to Windows Services. Verify both Apaches are listed

9) Start both services

10) Process Ready. Go to:

ip:80 --> app1 should be displayed

ip:5000 --> app2 should be displayed


What are your thoughts on this?




Graham Dumpleton

unread,
Sep 15, 2020, 11:24:26 PM9/15/20
to mod...@googlegroups.com
That is one way of solving the problem, although technically the other way should have worked except for that restriction about third party Python modules.

Have one question. Is that using mod_wsgi installed with 'pip install mod_wsgi', or were you using the develop version from GitHub?

The develop version on GitHub was broken in last few days for Windows and wouldn't compile. So if you were using that one, it must have been picking up an older build of it from Python cache on your local system, corresponding to before the point I broke it.

Reason I ask as the WSGIPythonHome shouldn't work with the version installed from PyPi.

Daniel Gutiérrez

unread,
Sep 15, 2020, 11:43:03 PM9/15/20
to mod...@googlegroups.com
I used the pip install mod_wsgi. I was unable to download the develop version from GitHub.

In any case, thank you very much for your help. You were quick to respond and very effective. I appreciate that a lot. 

Thanks man! Have a great day!

Sent from my iPhone

On Sep 15, 2020, at 9:24 PM, Graham Dumpleton <graham.d...@gmail.com> wrote:

That is one way of solving the problem, although technically the other way should have worked except for that restriction about third party Python modules.
Reply all
Reply to author
Forward
0 new messages