Deploying your Python Webhooks to Production on PythonAnywhere

March 02, 2021
Written by
Reviewed by
Diane Phan
Twilion

Deploying your Python Webhooks to Production on PythonAnywhere

If you have been following tutorials from this blog you probably know that Twilio uses the webhook pattern in many of its products. This pattern requires your application to expose its functionality behind public URLs that Twilio invokes at the proper times. In most of our tutorials, we show you how to run the application in your own computer, and make it accessible to Twilio through tools such as ngrok, which allocates temporary public URLs for privately running services.

That is a great workflow to use during development, but what do you do once your application is complete and you want to start using it for real? At this point you have to consider moving the application outside of your computer and into a permanent home on the Internet, with the help of a cloud hosting provider.

In this tutorial you will learn how to deploy your Python application on the PythonAnywhere platform.

Requirements

To follow this tutorial you will need the following:

  • A free or paid Twilio account. If you are new to Twilio create a free account now. If you create your account using this link and later upgrade to a paid account, you will receive $10 in credit.
  • A free or paid PythonAnywhere account. Create an account here.
  • A smartphone that can send and receive SMS (to test the deployed example application).

What is PythonAnywhere?

PythonAnywhere is an online hosting platform for applications built using the Python programming language. It provides bash and Python consoles that can be accessed directly from your web browser, as well as the infrastructure to deploy Python applications for production use.

An Example SMS Bot

In this article you are going to learn how to deploy an example SMS bot to PythonAnywhere. I’m not going to go over the implementation of the bot in this article, but if you are interested to learn more about it, this project is featured in another tutorial of mine.

The bot is implemented in a single Python file named bot.py. Later in this tutorial you will need to use the code for this application, so below is the complete listing for your reference.

from flask import Flask, request
import requests
from twilio.twiml.messaging_response import MessagingResponse

app = Flask(__name__)

@app.route('/bot', methods=['POST'])
def bot():
    incoming_msg = request.values.get('Body', '').lower()
    resp = MessagingResponse()
    msg = resp.message()
    responded = False
    if 'quote' in incoming_msg:
        # return a quote
        r = requests.get('https://api.quotable.io/random')
        if r.status_code == 200:
            data = r.json()
            quote = f'{data["content"]} ({data["author"]})'
        else:
            quote = 'I could not retrieve a quote at this time, sorry.'
        msg.body(quote)
        responded = True
    if 'cat' in incoming_msg:
        # return a cat pic
        msg.media('https://cataas.com/cat')
        responded = True
    if not responded:
        msg.body('I only know about famous quotes and cats, sorry!')
    return str(resp)


if __name__ == '__main__':
    app.run()

To install the application on PythonAnywhere, you’ll also need to use a requirements.txt file that contains all of the Python dependencies that it uses. Below is this file, once again, so that you can refer to it later in the tutorial.

certifi==2019.9.11
chardet==3.0.4
Click==7.0
Flask==1.1.1
idna==2.8
itsdangerous==1.1.0
Jinja2==2.10.3
MarkupSafe==1.1.1
PyJWT==1.7.1
pytz==2019.3
requests==2.22.0
six==1.13.0
twilio==6.33.1
urllib3==1.25.7
Werkzeug==0.16.0

Installing the Application

If you haven’t created an account on PythonAnywhere, do it now. A free account is sufficient to complete this tutorial and deploy the SMS bot shown in the previous section.

Creating a bash console

When you log in to your account, you will have a dashboard interface with four main sections titled “Consoles”, “Files”, “Notebooks” and “Web apps”. Click the “$ bash” button on the “Consoles” section to open a bash session into your account:

PythonAnywhere consoles

This will start a bash shell on your browser, similar to one you could have on your own computer.

bash console

Copying the application files

To host an application on this platform, you have to install all of its files in the home directory provided on this console session. For this tutorial you are going to install the application files directly on the home directory. If you wanted to host multiple applications on the same PythonAnywhere account, you can create a subdirectory for each application to help keep your code nicely organized.

The bash console provides access to two text editors: vi and nano. If you don’t have experience with any of them, use nano as it has a smaller learning curve. I will also use nano in the following examples, but feel free to replace it with vi if you are familiar with that editor.

For the next step you need to copy the bot.py and requirements.txt files shown in the previous section to the home directory of your PythonAnywhere account. The easiest way to do this is to copy/paste them. All of the code you need is provided in the previous section “An Example SMS Bot” labelled as bot.py. Copy all of it to the clipboard. Then in the PythonAnywhere bash console, open a bot.py file using your chosen text editor:

nano bot.py

Once you are in the editor, paste the code that you just copied. To exit nano, press Ctrl-X, and answer “Yes” when you are asked if you want to save the changes.

Now repeat the process with requirements.txt:

nano requirements.txt

Creating a Python virtual environment

To follow Python best practices, you should now create and activate a virtual environment. Use the following commands to do that:

python3 -m venv venv
source venv/bin/activate

The bash prompt should now have a (venv) prefix, which indicates that the virtual environment is activated. The next step is to install the Python dependencies referenced in the requirements.txt file:

pip install -r requirements.txt

Creating a Web Application

With the application files and Python configuration in place, it is now time to tell PythonAnywhere to allocate a web application. Click on the menu in the top-right corner of your bash console window and select “Dashboard”.

From the Dashboard, select “Web” in the navigation bar and click on “Add a new web app”.

PythonAnywhere web apps

You will now enter a step-by-step guided configuration tool. In the first step, you will be given the public URL under which your web application will be hosted. If you have a paid PythonAnywhere account, you can select a custom domain name, but on free accounts the domain is going to have the format <your-username>.pythonanywhere.com.

Click the “Next” button to continue to the next step.

Create web app

You will now be asked to select the Python web framework that your application uses. The example application is written using the Flask web framework, but I find it a lot more convenient to use the “Manual configuration” option, which actually works for all frameworks that are compatible with the WSGI protocol. Choose that option and select the latest Python version. Click “Next” to continue.

Select Python framework

Select python version

The next screen provides some information about how the manual configuration works. When you click “Next”, PythonAnywhere will create a configuration template for your web application in the /var/www directory of your account. Go ahead and click “Next” to move on to the final configuration step.

Manual configuration

On the last configuration page you will see all of the details about your new web application. At this point a basic “Hello, world” type application is deployed on your account.

Open a new tab on your web browser and visit the URL <your-username>.pythonanywhere.com to confirm that your account has this application deployed.

Hello world

Virtualenv configuration

Go back to the PythonAnywhere web application page. Scroll down to the section titled “Virtualenv”. In this section you have to configure the location of the virtual environment created earlier. Click on the “Enter path” line, and then type /home/<your-username>/venv, making sure to use type your PythonAnywhere username instead of <your-username>.

Virtualenv section

After you enter the name of the virtual environment, it should change to the full path, which should start with your home directory:

Virtualenv configured

WSGI configuration

Now find the section titled “Code”. The “WSGI configuration file” line has the full path of the WSGI configuration template file added by PythonAnywhere, which should have the format /var/www/<your-username>_pythonanywhere_com_wsgi.py:

Code section

Keep a mental note of the WSGI configuration file, or if you prefer, copy it to the clipboard. Click on “Consoles” in the navigation bar and then select your bash console under the “Your consoles” section. You should now be back into the bash session, exactly how you left it before.

Open a text editor on the WSGI configuration file:

nano /var/www/<your-username>_pythonanywhere_com_wsgi.py

You will see that this template file that PythonAnywhere generated is long and full of instructions for a lot of different use cases. Feel free to read through it if you are interested, but for the purposes of this tutorial you need to delete the contents of this file and replace them with a single line of Python code:

from bot import app as application

If you are using nano to edit this file, you can press Ctrl-K at the beginning of each line to delete it.

This line imports the app variable defined in bot.py and renames it to application. This variable is the WSGI application exported by the Flask framework. PythonAnywhere needs to access it with the longer name of application.

After you’ve made this change, save the WSGI configuration file. Then go back to the Web section of the PythonAnywhere dashboard and click the green “Reload” button to restart the web application with the final configuration.

Congratulations, your application is now deployed!

Testing the deployed application

The last configuration step is to connect the URL of the bot’s webhook to a Twilio phone number.

Buying a Twilio phone number

If you already have a phone number in your Twilio account, you can proceed to the following section.

Open the Twilio Console in your web browser and visit the Phone Numbers section to buy a phone number. If you have a trial account you will not be using real money here since you will pay for the number using the trial credits loaded into your account.

Select your country on the Buy a Number screen. You will also want to check SMS in the capabilities field. If you’d like to request a number from your region, you can enter your area code in the Number field.

Buy a Twilio number

Click the Search button to see what numbers are available, and then click “Buy” for the number that you like from the results. After you confirm your purchase, click the “Close” button.

The documentation provides more details about the phone number buying process.

Configuring the webhook URL

From the Phone Numbers section of the Twilio console, find the phone number that you purchased above and select it to enter its configuration page.

Scroll down to the “Messaging” section. In the “A message comes in” field you’ll now enter the URL for the webhook in the deployed application. This URL is composed of the PythonAnywhere URL with the path to the webhook, which is /bot, after it. In general the format of the URL is going to be https://<your-username>.pythonanywhere.com/bot. Enter this URL in the field as shown below:

Webhook configuration

Make sure the request method is set to HTTP POST, and then click the “Save” button at the bottom to record these configuration changes.

Chatting with your bot!

That’s it! Whenever Twilio receives an SMS message on the number you purchased, it will send a request to the bot’s endpoint running on PythonAnywhere. To try this out, grab your cell phone and send a text to the Twilio number. Note that if you are on a free Twilio account, you will have to verify your personal number before you can send text messages to Twilio.

Below you can see an example interaction I had with this bot:

Bot demo

Conclusion

I hope you found these instructions useful. If you decide to continue using PythonAnywhere consider upgrading to a paid account to avoid hitting the limitations of the free tier. In particular, PythonAnywhere requires free applications to be manually confirmed every three months, so make sure you pay attention to their emails if you want to keep your application online.

If you want to look at other Python friendly deployment options I also recommend you check out Heroku.

Do you use another deployment platform for your Twilio applications? I’d love to know which!

Miguel Grinberg is a Python Developer for Technical Content at Twilio. Reach out to him if you have a cool Python project you’d like to share on this blog!