The python documentation for modwsgi seems to fit what you are asking for. The following webpage has a really simple example and the necessary configuration for a python3-apache2 setup.

http://modwsgi.readthedocs.io/en/develop/user-guides/quick-configuration-guide.html

You will need to install the mod_wsgi for the configuration to work. Take note of the different "_" underscore and "-" dash character used in apt and pip3.

$ sudo apt install apache2-dev libapache2-mod-wsgi-py3
$ sudo pip3 install mod_wsgi

libapache2-mod-wsgi-py3 and mod_wsgi seems to be the same thing. However, my test deployment only works after installing mod_wsgi. Could be configuration issue. The following are the details of the configuration I have tested on Ubuntu 16.04.2.

Application file /home/user/wsgi_sample/hello.wsgi:

def application(environ, start_response):
    status = '200 OK'
    output = b'Hello World!'
    response_headers = [('Content-type', 'text/plain'),
                    ('Content-Length', str(len(output)))]
    start_response(status, response_headers)
    return [output]

Apache2 configuration /etc/apache2/sites-available/000-test.conf

<VirtualHost *:80>
  ServerName testmachine
  <Directory /home/user/wsgi_sample>
    Order allow,deny
    Allow from all
    Require all granted
  </Directory>
  WSGIScriptAlias /hello /home/user/wsgi_sample/hello.wsgi
</VirtualHost>

Enable the site in apache2.

sudo a2ensite 000-test.conf

Open your browser to testmachine/hello.

wsgi may also be deployed on Apache2 using passenger. It demands a slighter longer configuration. Ask a new question if passenger/python3 is desired.

Answer from Devakhim on Stack Overflow
Top answer
1 of 2
6

The python documentation for modwsgi seems to fit what you are asking for. The following webpage has a really simple example and the necessary configuration for a python3-apache2 setup.

http://modwsgi.readthedocs.io/en/develop/user-guides/quick-configuration-guide.html

You will need to install the mod_wsgi for the configuration to work. Take note of the different "_" underscore and "-" dash character used in apt and pip3.

$ sudo apt install apache2-dev libapache2-mod-wsgi-py3
$ sudo pip3 install mod_wsgi

libapache2-mod-wsgi-py3 and mod_wsgi seems to be the same thing. However, my test deployment only works after installing mod_wsgi. Could be configuration issue. The following are the details of the configuration I have tested on Ubuntu 16.04.2.

Application file /home/user/wsgi_sample/hello.wsgi:

def application(environ, start_response):
    status = '200 OK'
    output = b'Hello World!'
    response_headers = [('Content-type', 'text/plain'),
                    ('Content-Length', str(len(output)))]
    start_response(status, response_headers)
    return [output]

Apache2 configuration /etc/apache2/sites-available/000-test.conf

<VirtualHost *:80>
  ServerName testmachine
  <Directory /home/user/wsgi_sample>
    Order allow,deny
    Allow from all
    Require all granted
  </Directory>
  WSGIScriptAlias /hello /home/user/wsgi_sample/hello.wsgi
</VirtualHost>

Enable the site in apache2.

sudo a2ensite 000-test.conf

Open your browser to testmachine/hello.

wsgi may also be deployed on Apache2 using passenger. It demands a slighter longer configuration. Ask a new question if passenger/python3 is desired.

2 of 2
0

Yes, your minimum code seem correct. The Apache config information is answered here https://stackoverflow.com/a/57531411/4084546

Top answer
1 of 2
37

I think you have installed mod_wsgi for python2 with this command:

sudo apt-get install libapache2-mod-wsgi

But if you want to use mod_wsgi with python3, you should install correct mod_wsgi with this command:

sudo apt-get install libapache2-mod-wsgi-py3
2 of 2
4

To change a python version on per user basis you simply create an alias within user's home directory. Open ~/.bashrc file and add new alias to change your default python executable:

alias python='/usr/bin/python3.4'

Once you make the above change, re-login or source your .bashrc file:

$ . ~/.bashrc

Check your default python version:

$ python --version
Python 3.4.2

Change python version system-wide

To change python version system-wide we can use update-alternatives command. Logged in as a root user, first list all available python alternatives:

# update-alternatives --list python
update-alternatives: error: no alternatives for python

The above error message means that no python alternatives has been recognized by update-alternatives command. For this reason we need to update our alternatives table and include both python2.7 and python3.4:

# update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
update-alternatives: using /usr/bin/python2.7 to provide /usr/bin/python     (python) in auto mode
# update-alternatives --install /usr/bin/python python /usr/bin/python3.4 2
update-alternatives: using /usr/bin/python3.4 to provide /usr/bin/python (python) in auto mode

The --install option take multiple arguments from which it will be able to create a symbolic link. The last argument specified it priority means, if no manual alternative selection is made the alternative with the highest priority number will be set. In our case we have set a priority 2 for /usr/bin/python3.4 and as a result the /usr/bin/python3.4 was set as default python version automatically by update-alternatives command.

# python --version
Python 3.4.2

Next, we can again list all python alternatives:

# update-alternatives --list python
/usr/bin/python2.7
/usr/bin/python3.4

From now on, we can anytime switch between the above listed python alternative versions using below command and entering a selection number:

# update-alternatives --config python
Discussions

How to use Python 3 and Django with Apache? - Stack Overflow
I have an AWS EC3 Ubuntu instance running Python3, Django 1.5.6, Apache2.2 and mod_wsgi 3.4 More on stackoverflow.com
🌐 stackoverflow.com
March 1, 2014
apache - Executing a Python script in Apache2 - Stack Overflow
I am trying to execute a Python program using Apache. However, Apache will only serve the file and not actually execute it. The permissions on the file are r/w/x and it is in /var/www. I will po... More on stackoverflow.com
🌐 stackoverflow.com
ubuntu - How to get apache to use python3.6 and its modules? - Stack Overflow
By default the version of python ... default python3 version (I verified this by printing sys.version_info in my .wsgi file). Because of this it none of my modules are in the path. After looking around I found the apache config options WSGIPythonHome and WSGIPythonPath. I have tried adding these to my apache.confin different combinations but nothing has worked. Below is what I tried and what the errors were. # /etc/apache2/apache.conf ... More on stackoverflow.com
🌐 stackoverflow.com
Quickest way to run python script via apache on Debian (11) - Unix & Linux Stack Exchange
So recently I wanted to remotely trigger a python script, apache was already installed and Im familiar with it so figured id look into that, another option would be to code a custom socket server in More on unix.stackexchange.com
🌐 unix.stackexchange.com
March 25, 2022
🌐
Linux.com
linux.com › home › training and tutorials › configuring apache2 to run python scripts
Configuring Apache2 to run Python Scripts - Linux.com
January 14, 2014 - The first step is getting Apache2 to recognize that my .py files were to be executed and not spit out as text files.
🌐
Matrixpost
blog.matrixpost.net › home › general › enable python for apache websites
Enable Python for Apache Websites - .matrixpost.net
July 6, 2024 - By default you will execute Python3 with the python3 command, by installing the packet below, you can execute Python3 also as usual with the command python.
🌐
DigitalOcean
digitalocean.com › community › tutorials › how-to-set-up-an-apache-mysql-and-python-lamp-server-without-frameworks-on-ubuntu-14-04
How To Set Up an Apache, MySQL, and Python (LAMP) Server Without Frameworks on Ubuntu 14.04 | DigitalOcean
April 29, 2015 - This article will walk you through setting up a server with Python 3, MySQL, and Apache2, sans the help of a framework. By the end of this tutorial, you will…
🌐
Abdul Wahab Junaid
awjunaid.com › home › how to install and configure python with apache
How to install and configure Python with Apache | Abdul Wahab Junaid
September 11, 2023 - #!/usr/bin/env python3 import sys import os # Add your application's directory to the sys.path sys.path.append('/var/www/html/myapp') # Load your application from your_application import app as application # Replace 'your_application' with your actual application name if __name__ == '__main__': # For testing purposes from werkzeug.serving import run_simple run_simple('localhost', 4000, application)
Top answer
1 of 5
14

Django 1.6+ and mod_wsgi 3.4+ are required to use Python 3 with Apache. For more detail refer to scot's answer.

2 of 5
11

These answers are no longer true of Django 1.6 - it supports python3. The mod_wsgi page says version 3.4 supports python 3. https://code.google.com/p/modwsgi/

Don't know if it all works at this point though (I will return and edit when I find out)!

The answer is YES it works!

I have an AWS EC3 Ubuntu instance running Python3, Django 1.5.6, Apache2.2 and mod_wsgi 3.4

Python 3.3.4:

sudo add-apt-repository ppa:fkrull/deadsnakes
sudo apt-get install python3.3
sudo apt-get install python3.3-dev python3.3-doc idle-python3.3

ppa:fkrull/deadsnakes is a apt repo has has multiple python versions available - see https://launchpad.net/~fkrull/+archive/deadsnakes

Then I added pip using the instructions at the pip page; http://pip.readthedocs.org/en/latest/installing.html. (remember your python is probably on your path as 'python3.3' at this point, plain 'python' will point at python 2.x!)

After that, virtualenv. Then I virtualenv'd the python installation. Upon activation and adding the environment's bin/ directory to the $PATH I've now got a clean python3.

Then, after I activated the virtual env, I did 'pip Django' and all my other necessary packages (which were quite a few). I have Django version 1.6.2 (I've been developing on this and running under python 3.3.3 on my Mac no problem).

The most trouble I had was installing lxml because it requires libxml2 and libxslt to be installed with apt-get (it is a wrapper around the C code) and it took me a couple of attempts to realise that they were not already installed (lxml compilation fails).

After tossing about getting my RDS database instance up and running and available (postgresql, beware mysql under python3, you'll get plenty of python db driver pain! but most of my issues were caused by me trying to understand the AWS security configuration), it was relatively plain sailing:

sudo apt-get install apache2 apache2-threaded-dev

That installs apache - and you need the dev packages for the next bit.

And that point, I tried using the apt package for mod_wsgi but I decided that the best thing to do was to compile and install it myself, following the instructions here - https://code.google.com/p/modwsgi/wiki/InstallationInstructions

I had no problems with configure, make, or make install. Make sure you compile it in your virtualenv activated environment.

You have to manually add the configuration to Apache's configuration:

# wsgi module
LoadModule wsgi_module /usr/lib/apache2/modules/mod_wsgi.so
# now configure it
<Directory /my/app/path>
 <Files wsgi.py>
  Order deny,allow
  Allow from all
 </Files>
</Directory>
WSGIScriptAlias / /my/app/path/wsgi.py
WSGIPythonPath /my/app:/path/to/the/virtual/env/lib/python3.3/site-packages

And in the broadest possible way, this is all now working.

Find elsewhere
🌐
HowtoForge
howtoforge.com › home › how to run python scripts with apache and mod_wsgi on ubuntu 22.04
How to run Python Scripts with Apache and mod_wsgi on Ubuntu 22.04
sudo apt install python3 libexpat1 -y · The screenshot below shows the output of the command when python is already installed. Now proceed with the next step. In this step, we will install the Apache web server and the mod_wsgi Python module. Execute the following command to install both applications. The dependent software packages will get installed automatically. sudo apt install apache2 apache2-utils ssl-cert libapache2-mod-wsgi-py3 -y ·
Top answer
1 of 6
20

The first line of httpd.conf: AddHandler cgi-script .cgi .pl is irrelevant, since you're testing python scripts and not perl scripts. And you should define those directives within the location of your python script, and tell apache that it should execute cgi scripts in that location: Options +ExecCGI. This snippet would be a start:

<Directory /path/to/sample.py />
  Options +ExecCGI
  AddHandler cgi-script .py
</Directory>

Addendum 1:

As per my last comment, try this script. It should spit information about the cgi environment.

#!/usr/bin/python
import cgi
cgi.test()

Addendum 2:

I got your script to work with the above configuration. The problem is that script is written in python2. And the default interpreter apache is invoking to execute the script, is python3 (at least in my case, and chances are this would be the same for you too).

This is a python3 version of the hello world script:

#!/usr/bin/env python

# enable debugging
import cgitb
cgitb.enable()

print("Content-Type: text/plain;charset=utf-8")
print()

print("Hello World!")

Addendum 3:

For the first error, make sure the permission and the ownership of whatever directory and files you're attempting to deploy are properly set. And try adding those directives to httpd.conf:

Order allow,deny
Allow from all

Which will get you this:

<Directory /path/to/sample.py />
  Options +ExecCGI
  AddHandler cgi-script .py
  Order allow,deny
  Allow from all
</Directory>

For the second error, unless I am missing something, it looks like apache is invoking python 3 interpreter to execute your script. To rule out this possibility, you might try the following:

ls -al /usr/bin/python*

This will list the python interpreters available on your system. If you have more than one interpreter you'll get something similar to this output:

/usr/bin/python -> python3*
/usr/bin/python2.6*  
/usr/bin/python3*  

If not, it would be this output:

/usr/bin/python -> python2.6*
/usr/bin/python2.6*  

To make sure, this is not the issue you're having, try with this modified sample script:

#!/usr/bin/python2.6

# enable debugging
import cgitb
cgitb.enable()

print "Content-Type: text/plain\r\n\r\n"
print

print "Hello World!"

You'll notice that I explicitly mentioned the version of the interpreter apache should invoke, which is ugly. But for the sake of testing, you can do it. Of course you should map #!/usr/bin/python2.6, to whatever binary you have on your server, and make sure you don't mix python 3 comtipable code with python 2 interpreter and vice versa.

2 of 6
3

Re: The Exec format error.

I've run in to this myself a couple of times before. I had the exact same (cryptic) error message.

I was developing Python (3) scripts to use via CGI in Notepad++ on my Windows machine, and then uploading them to my Linux server.

After much frustration, I discovered that this issue is related to line endings and you need to convert Windows line endings (\r\n) to UNIX line endings (\n).

In Notepad++ (6.1.5), you can achieve this by going to the Edit menu and selecting the EOL conversion option and then saving the file.

🌐
Raspberry Pi Forums
forums.raspberrypi.com › board index › projects › networking and servers
Running python3 on apache2, try to aceed the file.. 403DENIED - Raspberry Pi Forums
You can try changing the ownership and permissions of the script using the following commands: sudo chown www-data:www-data /var/www/html/myscript.py sudo chmod 755 /var/www/html/myscript.py This changes the ownership of the file to the Apache2 user and group, and sets the file permissions to allow execution.
🌐
Martin Thoma
martin-thoma.com › execute-python-on-apache2
Execute Python on Apache2 · Martin Thoma
I have to run a very simple Python script on an Apache2 web server. These were the steps with which I made it work: Find the Apache2 config $ /usr/sbin/apache2 -V It is in /etc/apache2/apache2.conf Add CGI Somewhere in the /etc/apache2/apache2.conf there is …
🌐
Edureka Community
edureka.co › home › community › categories › python › how to use python 3 and django with apache
How to use Python 3 and Django with Apache | Edureka Community
July 3, 2020 - My goal is to set up Python 3 with Apache. My biggest problem is actually acquiring mod_python.so. so how can we do that?Any help?
🌐
HowtoForge
howtoforge.com › home › embedding python in apache2 with mod_python (debian etch)
Embedding Python In Apache2 With mod_python (Debian Etch)
This tutorial shows how to install and use mod_python on a Debian Etch server with Apache2. mod_python is an Apache module that embeds the Python interpreter within the server.
🌐
Medium
medium.com › @jennytan5522 › complete-guide-to-setting-up-a-python-web-server-on-ubuntu-8635596b0601
Complete Guide to Setting Up a Python Web Server on Ubuntu | by Jenny Tan | Medium
November 8, 2025 - sudo apt install -y certbot python3-certbot-apache sudo certbot --apache · 📍Using SSL/TLS encryption helps prevent man-in-the-middle attacks and ensures secure, seamless communication between the web server and its clients. Creating a new virtual host file: sudo nano /etc/apache2/sites-available/my_web_app.conf ·
Top answer
1 of 1
2

While there are several was to do it such as apache CGI (this method), mod_python or mod_wsgi, of which neither take very long to setup. I found this method to have the least steps.

First step to enable cgi mod (a2enmod in my case was not in my default path, but was found in /usr/sbin/)

/usr/sbin/a2enmod cgi

systemctl restart apache2

That is it !! now if you put a .sh or .py script in /usr/lib/cgi-bin folder and make it owner root and execute permission it can be accessed from the web address

http://machine_address/cgi-bin/script.py

note that you need to have your shebang at the start of your script

#!/usr/bin/python3
print("Content-Type: text/html;charset=utf-8")
print ("Content-type:text/html\r\n")
print("<H1> Hello, From python server :) </H1>")

Going Further:

  • You can keep the script somewhere more convenient for editing such as your home dir or a repo, and simlink it to /usr/lib/cgi-bin, just chown the group to your user group while keeping the owner root, and set perms to 775

  • You can access the submitted query url for GET params with: (after import os)

    queryString = os.environ.get('QUERY_STRING')
    
  • Even though the cgi script must be owned by root to run, inside the python script any code is run as user www-data (default apache user). This might be fine, but if you need it as a different user, such as your 'normal' user account, one option (which i looked into) is mod_suexec which allows specifying the user a cgi script runs as. But I found it easier to just change the default user that apache runs as to my main user account. Its quicker/simpler and then I can access the error log files without su to root (to see python errors), and interact with my home files. Set user/grp in:(followed by restart)

    /etc/apache2/envvars
    
  • You can customise settings more look in eg cgi path, symlink perms etc.

     /etc/apache2/conf-enabled/serve-cgi-bin.conf
    
  • You can have python output errors in pretty html on your page, rather than to apache error.log by adding this to the top of your script:

    import cgitb
    cgitb.enable()