Writing an API in Python (with Flask and RapidAPI)

Writing an API in Python (with Flask and RapidAPI)

If you are reading this article, you are probably already familiar with the possibilities that open up when using the API (Application Programming Interface).

By adding one of the many public APIs to your application, you can extend the functionality of this application or supplement it with the necessary data. But what if you have developed a unique feature that you want to share with the community?

The answer is simple: you need create your own API.

While this may seem like a daunting task at first, it's actually quite simple. We'll show you how to do this with Python.

What you need to get started

API development requires:

  • Python3;
  • Flask β€” a simple and easy-to-use framework for creating web applications;
  • Flask-RESTful is an extension for Flask that allows you to develop a REST API quickly and with minimal configuration.

Installation is performed by the command:

pip install flask-restful

We recommend a free intensive programming for beginners:
Telegram bot development in C# β€” August 26–28. A free intensive that allows you to understand how helper bots work, the features of working with the Telegram API and other nuances. The top three participants will receive 30 rubles from Skillbox.

Before you start

We are going to develop a RESTful API with a basic CRUID functionality.

To fully understand the task, let's understand the two terms mentioned above.

What is REST?

REST API (Representational State Transfer) is an API that uses HTTP requests to exchange data.

REST APIs must meet certain criteria:

  • Client-server architecture: the client interacts with the user interface, and the server interacts with the backend and data store. The client and server are independent, any of them can be replaced separately from the other.
  • Stateless - No client data is stored on the server. The session state is stored on the client side.
  • Cacheability - Clients can cache server responses to improve overall performance.

What is CRUD?

CRUEL is a programming concept that describes four basic actions (create, read, update and delete).

In the REST API, request types and request methods are responsible for actions such as post, get, put, delete.

Now that we have dealt with the basic terms, we can start creating the API.

Development

Let's create a repository of quotes about artificial intelligence. AI is one of the fastest growing technologies today, and Python is a popular tool for working with AI.

With this API, a Python developer can quickly learn about AI and be inspired by new achievements. If the developer has valuable thoughts on this topic, he will be able to add them to the repository.

Let's start by importing the required modules and setting up Flask:

from flask import Flask
from flask_restful import Api, Resource, reqparse
import random
app = Flask(__name__)
api = Api(app)

In this snippet, Flask, Api and Resource are the classes we need.

Reqparse is a Flask-RESTful request parsing interface... You will also need the random module to display a random quote.

Now we will create a repository of quotes about AI.

Each repo entry will contain:

  • digital ID;
  • the name of the author of the quote;
  • quote.

Since this is just a learning example, we will store all entries in a Python list. In a real application, we would most likely use a database instead.

ai_quotes = [
    {
        "id": 0,
        "author": "Kevin Kelly",
        "quote": "The business plans of the next 10,000 startups are easy to forecast: " +
                 "Take X and add AI."
    },
    {
        "id": 1,
        "author": "Stephen Hawking",
        "quote": "The development of full artificial intelligence could " +
                 "spell the end of the human race… " +
                 "It would take off on its own, and re-design " +
                 "itself at an ever increasing rate. " +
                 "Humans, who are limited by slow biological evolution, " +
                 "couldn't compete, and would be superseded."
    },
    {
        "id": 2,
        "author": "Claude Shannon",
        "quote": "I visualize a time when we will be to robots what " +
                 "dogs are to humans, " +
                 "and I’m rooting for the machines."
    },
    {
        "id": 3,
        "author": "Elon Musk",
        "quote": "The pace of progress in artificial intelligence " +
                 "(I’m not referring to narrow AI) " +
                 "is incredibly fast. Unless you have direct " +
                 "exposure to groups like Deepmind, " +
                 "you have no idea how fast β€” it is growing " +
                 "at a pace close to exponential. " +
                 "The risk of something seriously dangerous " +
                 "happening is in the five-year timeframe." +
                 "10 years at most."
    },
    {
        "id": 4,
        "author": "Geoffrey Hinton",
        "quote": "I have always been convinced that the only way " +
                 "to get artificial intelligence to work " +
                 "is to do the computation in a way similar to the human brain. " +
                 "That is the goal I have been pursuing. We are making progress, " +
                 "though we still have lots to learn about " +
                 "how the brain actually works."
    },
    {
        "id": 5,
        "author": "Pedro Domingos",
        "quote": "People worry that computers will " +
                 "get too smart and take over the world, " +
                 "but the real problem is that they're too stupid " +
                 "and they've already taken over the world."
    },
    {
        "id": 6,
        "author": "Alan Turing",
        "quote": "It seems probable that once the machine thinking " +
                 "method had started, it would not take long " +
                 "to outstrip our feeble powers… " +
                 "They would be able to converse " +
                 "with each other to sharpen their wits. " +
                 "At some stage therefore, we should " +
                 "have to expect the machines to take control."
    },
    {
        "id": 7,
        "author": "Ray Kurzweil",
        "quote": "Artificial intelligence will reach " +
                 "human levels by around 2029. " +
                 "Follow that out further to, say, 2045, " +
                 "we will have multiplied the intelligence, " +
                 "the human biological machine intelligence " +
                 "of our civilization a billion-fold."
    },
    {
        "id": 8,
        "author": "Sebastian Thrun",
        "quote": "Nobody phrases it this way, but I think " +
                 "that artificial intelligence " +
                 "is almost a humanities discipline. It's really an attempt " +
                 "to understand human intelligence and human cognition."
    },
    {
        "id": 9,
        "author": "Andrew Ng",
        "quote": "We're making this analogy that AI is the new electricity." +
                 "Electricity transformed industries: agriculture, " +
                 "transportation, communication, manufacturing."
    }
]

Now we need to create a Quote resource class that will define the operations of our API endpoints. Four methods must be declared inside the class: get, post, put, delete.

Let's start with the GET method

It allows you to get a specific quote by specifying its ID, or a random quote if no ID is specified.

class Quote(Resource):
    def get(self, id=0):
        if id == 0:
            return random.choice(ai_quotes), 200
        for quote in ai_quotes:
            if(quote["id"] == id):
                return quote, 200
        return "Quote not found", 404

The GET method returns a random quote if the ID contains the default value, i.e. when calling the method ID was not set.

If it is set, then the method searches among quotes and finds the one that contains the given ID. If nothing is found, the message β€œQuote not found, 404” is displayed.

Remember, the method returns an HTTP status of 200 if the request was successful and 404 if the entry was not found.

Now let's create a POST method to add a new quote to the repository

It will get the id of each new quote as you type. In addition, POST will use reqparse to parse the parameters that will go in the request body (author and quote text).

def post(self, id):
      parser = reqparse.RequestParser()
      parser.add_argument("author")
      parser.add_argument("quote")
      params = parser.parse_args()
      for quote in ai_quotes:
          if(id == quote["id"]):
              return f"Quote with id {id} already exists", 400
      quote = {
          "id": int(id),
          "author": params["author"],
          "quote": params["quote"]
      }
      ai_quotes.append(quote)
      return quote, 201

In the code above, the POST method accepted a quote ID. Then, using reqparse, it retrieved the author and quote from the request, storing them in the params dictionary.

If a quote with the specified ID already exists, then the method displays the appropriate message and code 400.

If a quote with the specified ID has not yet been created, the method creates a new entry with the specified ID and author, as well as other parameters. It then adds an entry to the ai_quotes list and returns an entry with a new quote along with a 201 code.

Now we create a PUT method to change an existing quote in the repository

def put(self, id):
      parser = reqparse.RequestParser()
      parser.add_argument("author")
      parser.add_argument("quote")
      params = parser.parse_args()
      for quote in ai_quotes:
          if(id == quote["id"]):
              quote["author"] = params["author"]
              quote["quote"] = params["quote"]
              return quote, 200
      
      quote = {
          "id": id,
          "author": params["author"],
          "quote": params["quote"]
      }
      
      ai_quotes.append(quote)
      return quote, 201

The PUT method, similar to the previous example, takes an ID and an input and parses the quote parameters using reqparse.

If a quote with the specified ID exists, the method will update it with the new parameters and then output the updated quote with code 200. If there is no quote with the specified ID yet, a new record with code 201 will be created.

Finally, let's create a DELETE method to remove a quote that is no longer inspiring.

def delete(self, id):
      global ai_quotes
      ai_quotes = [qoute for qoute in ai_quotes if qoute["id"] != id]
      return f"Quote with id {id} is deleted.", 200

This method takes the quote ID as input and updates the list of ai_quotes using the shared list.

Now that we've created all the methods, all we need to do is simply add the resource to the API, set the path, and run Flask.

api.add_resource(Quote, "/ai-quotes", "/ai-quotes/", "/ai-quotes/<int:id>")
if __name__ == '__main__':
    app.run(debug=True)

Our REST API Service is ready!

Next, we can save the code to the app.py file by running it in the console with the command:

python3 app.py

If everything is fine, then we will get something like this:

* Debug mode: on
*Running on 127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: XXXXXXX

Testing the API

After the API is created, it needs to be tested.

This can be done using the curl console utility or the Insomnia REST client, or by publishing the API on the Rapid API.

Writing an API in Python (with Flask and RapidAPI)

Publishing our API

RapidAPI is the largest marketplace in the world with over 10 APIs (and about 000 million developers).

RapidAPI not only provides a single interface for working with third-party APIs, but also allows you to quickly and easily publish your own API.

To do it, you first need to publish it to some server on the network. In our case, we will use Heroku. Working with him should not cause any difficulties, (you can find out more about it here).

How to publish your API on Heroku

1. Install Heroku.

The first step is to register and install the Heroku Command Line Interface (CLI). This works on Ubuntu 16+.

sudo snap install heroku --classic

Then we log in:

heroku login

2. Add the necessary files.

Now we need to add the files to publish to a folder in our application:

  • requirements.txt with a list of required Python modules;
  • Procfile, which specifies which commands must be executed to run the application;
  • .gitignore - to exclude files that are not needed on the server.

The requirements.txt file will contain the following lines:

  • flask
  • flask-restful
  • gunicorn

Please note that we have added gunicorn (Python WSGI HTTP Server) to the list because we need to run our application on the server.

Procfile will contain:

web: gunicorn app:app

Content of .gitignore:

*.pyc
__pycache__/

Now that the files are created, let's initialize the git repo and commit:

git init
git add
git commit -m "First API commit"

3. Create a new Heroku app.

heroku create

Pushing the master branch to the remote Heroku repo:

git push heroku master

Now you can start by opening the API Service with the commands:

heroku ps:scale web=1
heroku open
 

The API will be available at your-random-heroku-name.herokuapp.com/ai-quotes.

How to add your Python API to the RapidAPI marketplace

Once the API service is published on Heroku, you can add it to the Rapid API. Here detailed documentation on this topic.

1. Create a RapidAPI account.

Writing an API in Python (with Flask and RapidAPI)

We register a free account - this can be done using Facebook, Google, GitHub.

Writing an API in Python (with Flask and RapidAPI)

2. Add API to the control panel.

Writing an API in Python (with Flask and RapidAPI)

3. Next, enter general information about your API.

Writing an API in Python (with Flask and RapidAPI)

4. After clicking β€œAdd API” a new page appears where you can enter information about our API.

Writing an API in Python (with Flask and RapidAPI)

5. Now you can either manually enter the API endpoints, or download swagger file using OpenAPI.

Writing an API in Python (with Flask and RapidAPI)

Well, now you need to set the endpoints of our API on the Endpoints page. In our case, the endpoints correspond to the concept of CRUD (get, post, put, delete).

Writing an API in Python (with Flask and RapidAPI)

Next, you need to create a GET AI Quote endpoint that displays a random quote (if the ID is default) or a quote for the specified ID.

To create an endpoint, you need to click the β€œCreate Endpoint” button.

Writing an API in Python (with Flask and RapidAPI)

We repeat this process for all other API endpoints. That's all! Congratulations, you have published your API!

If all goes well, the API page will look something like this:

Writing an API in Python (with Flask and RapidAPI)

Conclusion

In this article, we walked through the process of creating our own RESTful API Service in Python, along with the process of publishing the API to the Heroku cloud and adding it to the RapidAPI directory.

But in the test version, only the basic principles of API development were shown - such nuances as security, fault tolerance and scalability were not considered.

When developing a real API, all this must be taken into account.

Source: habr.com

Add a comment