One place for hosting & domains

      Python

      How To Build a Python REST API with Fauna and Deploy it to DigitalOcean App Platform


      Introduction

      Many developers don’t have the time or experience to set up and manage infrastructure for their applications. To keep up with deadlines and reduce costs, developers need to find solutions that allow them to deploy their apps to the cloud as quickly and efficiently as possible to focus on writing the code and delivering new features to their customers. Together, DigitalOcean’s App Platform and Fauna provide that ability.

      DigitalOcean App Platform is a Platform-as-a-Service (PaaS) that abstracts the infrastructure that runs your apps. It also lets you deploy applications by pushing your code to a Git branch.

      Fauna is a powerful data layer for applications of any size. As you’ll see in this tutorial, with Fauna, you can get a database up and running quickly without having to worry about the database operations.

      Together, these two solutions let you focus on your application instead of managing your infrastructure.

      In this tutorial, you’ll integrate Fauna with Python by writing a minimal REST API using the Flask framework. You’ll then deploy the API to DigitalOcean’s App Platform from a Git repository.The API will consist of:

      • A public /signup POST endpoint for creating users in the Users collection.
      • A public /login POST endpoint for authenticating with the documents in the Users collection.
      • A private /things GET endpoint for fetching a list of Fauna documents from the Things collection.

      The finished Python project is available at this Github repository.

      Prerequisites

      Before starting this tutorial, you will need:

      Step 1 — Setting Up the Fauna Database

      In the first step, you will configure a Fauna database and create the collections for the API. Fauna is a document-based database rather than a traditional table-based relational database. Fauna stores your data in documents and collections, which are groups of documents.

      To create the collections, you will execute queries using FQL, Fauna’s native query language. FQL is an expressive and powerful query language that gives you access to the full power of Fauna.

      To get started, log into Fauna’s dashboard. After logging in, click on the Create Database button at the top.

      In the New Database form, use PYTHON_API for the database name:

      Creating a Fauna database

      Leave Pre-populate with demo data unchecked. Press the Save button.

      After creating the database, you will see the home section for your database:

      Fauna database home

      You’re now going to create two collections:

      • The Users collection that will store documents with authentication information.
      • The Things collection to store some mock data to test your API.

      To create these collections, you’ll execute some FQL queries in the dashboard’s shell. Access the shell from the main dashboard menu on the left:

      Fauna dashboard shell

      Write the following FQL query in the bottom panel of the shell to create a collection called Things by using the CreateCollection function:

      CreateCollection({name: "Things"})
      

      Press the RUN QUERY button. You will get a result similar to this in the shell’s top panel:

      {
        ref: Collection("Things"),
        ts: 1614805457170000,
        history_days: 30,
        name: "Things"
      }
      

      The result shows four fields:

      • ref is a reference to the collection itself.
      • ts is the timestamp of its creation in microseconds.
      • history_days is how long Fauna will retain changes on documents’ changes.
      • name is the collection name.

      Next, create the Users collection with the following query:

      CreateCollection({name: "Users"})
      

      Now that both collections are in place, you will create your first document.

      Documents in Fauna are somewhat similar to JSON objects. Documents can store strings, numbers, and arrays, but they can also use Fauna data types. A common Fauna type is Ref, which represents a reference to a document in a collection.

      The Create function creates a new document into the specified collection. Run the following query to create a document in the Things collection with two fields:

      Create(
        Collection("Things"),
        {
          data: {
            name: "Banana",
            color: "Yellow"
          }
        }
      )
      

      After running that query, Fauna will return the created document:

      {
        ref: Ref(Collection("Things"), "292079274901373446"),
        ts: 1614807352895000,
        data: {
          name: "Banana",
          color: "Yellow"
        }
      }
      

      The result shows the following fields:

      • ref of type Ref is a reference to this document in the Things collection with the ID 292079274901373446. Do note that your document will have a different ID.
      • ts is the timestamp of its creation in microseconds.
      • data is the actual content of the document.

      This result looks similar to the result you got when you created a collection. That’s because all entities in Fauna (collections, indexes, roles, etc) are actually stored as documents.

      To read documents, use the Get function which accepts a reference of a document. Run the Get query using the reference for your document:

      Get(Ref(Collection("Things"), "292079274901373446"))
      

      The result is the full document:

      {
        ref: Ref(Collection("Things"), "292079274901373446"),
        ts: 1614807352895000,
        data: {
          name: "Banana",
          color: "Yellow"
        }
      }
      

      To get all references for documents stored in a collection, use the Documents function with the Paginate function:

      Paginate(Documents(Collection("Things")))
      

      This query returns a page with an array of references:

      {
        data: [Ref(Collection("Things"), "292079274901373446")]
      }
      

      To get actual documents instead of references, iterate over the references using Map. Then use a Lambda (an anonymous function) to iterate over the array of references and Get each reference:

      Map(
        Paginate(Documents(Collection("Things"))),
        Lambda("ref", Get(Var("ref")))
      )
      

      The result is an array containing full documents:

      {
        data: [
          {
            ref: Ref(Collection("Things"), "292079274901373446"),
            ts: 1614807352895000,
            data: {
              name: "Banana",
              color: "Yellow"
            }
          }
        ]
      }
      

      You’re now going to create the Users_by_username index. You typically use indexes in Fauna to catalog, filter, and sort data, but you can also use them for other purposes like enforcing unique constraints.

      The Users_by_username index will find users by their username, and also enforce a unique constraint to prevent two documents from having the same username.

      Execute this code in the shell to create the index:

      CreateIndex({
        name: "Users_by_username",
        source: Collection("Users"),
        terms: [{ field: ["data", "username"] }],
        unique: true
      })
      

      The CreateIndex function will create an index with the configured settings:

      • name is the name of the index.
      • source is the collection (or collections) the index will index data from.
      • terms is the search/filter terms you’ll pass to this index when using it to find documents.
      • unique means that the indexed values will be unique. In this example, the username property of the documents in the Users collection will be enforced as unique.

      To test the index, create a new document inside the Users collection by running the following code in the Fauna shell:

      Create(
        Collection("Users"),
        {
          data: {
            username: "sammy"
          }
        }
      )
      

      You’ll see a result like the following:

      {
        ref: Ref(Collection("Users"), "292085174927098368"),
        ts: 1614812979580000,
        data: {
          username: "sammy"
        }
      }
      

      Now try to create a document with the same username value:

      Create(
        Collection("Users"),
        {
          data: {
            username: "sammy"
          }
        }
      )
      

      You’ll receive an error now:

      Error: [
        {
          "position": [
            "create"
          ],
          "code": "instance not unique",
          "description": "document is not unique."
        }
      ]
      

      Now that the index is in place, you can query it and fetch a single document. Run this code in the shell to fetch the sammy user using the index:

      Get(
        Match(
          Index("Users_by_username"),
          "sammy"
        )
      )
      

      Here’s how it works:

      • Index returns a reference to the Users_by_username index.
      • Match returns a reference to the matched document (the one that has a username with the value of sammy).
      • Get takes the reference returned by Match, and fetches the actual document.

      The result of this query will be:

      {
        ref: Ref(Collection("Users"), "292085174927098368"),
        ts: 1614812979580000,
        data: {
          username: "sammy"
        }
      }
      

      Delete this testing document by passing its reference to the Delete function:

      Delete(Ref(Collection("Users"), "292085174927098368"))
      

      Next you’ll configure security settings for Fauna so you can connect to it from your code.

      Step 2 — Configuring a Server Key and Authorization Rules

      In this step you’ll create a server key that your Python application will use to communicate with Fauna. Then you’ll configure access permissions.

      To create a key, go to the Security section of the Fauna dashboard by using the main menu on the left. Once there:

      1. Press the New Key button.
      2. Select the Server role.
      3. Press Save.

      Creating a Fauna key

      After saving, the dashboard will show you the key’s secret. Save the secret somewhere safe and never commit it to your Git repository.

      Warning: The Server role is omnipotent and anyone with this secret would have full access to your database. As its name implies, this is the role typically used by trusted server applications, although it is also possible to create a key with a custom role with limited privileges. When you create production applications, you’ll want to make a more restrictive role.

      By default, everything in Fauna is private, so you’re now going to create a new role to allow the logged-in users to read documents from the Things collection.

      In the Security section of the dashboard, go to Roles, and create a new custom role with the name User.

      In the Collections dropdown, add the Things collection and press the Read permission so that it shows a green check mark:

      Configuring the permissions of a Fauna role

      Before saving the role, go to the Membership tab and add the Users collection to the role:

      Configuring the memerbship of a Fauna role

      You can now save your User custom role by pressingthe Save button.

      Now any logged-in user from a document in the Users collection will be able to read any document from the Things collection.

      With authentication and authorization in place, let’s now create the Python API that will talk to Fauna.

      Step 3 — Building the Python Application

      In this step you will build a small REST API using the Flask framework, and you’ll write FQL queries in Python, connecting to your Fauna database using the the Fauna driver.

      To get started, create a project folder and access it from your terminal.

      First install Flask with:

      Then install the Fauna Python driver with:

      In your project folder, create the file main.py and add the following code to the file, which adds the necessary imports, the FAUNA_SECRET environment variable, and the basic configuration of the Flask application:

      main.py

      import os
      FAUNA_SECRET = os.environ.get('FAUNA_SECRET')
      
      import flask
      from flask import request
      
      import faunadb
      from faunadb import query as q
      from faunadb.client import FaunaClient
      
      app = flask.Flask(__name__)
      app.config["DEBUG"] = True
      

      The FAUNA_SECRET environment variable will carry the server secret you created earlier. To be able to run this application, locally or in the cloud, this variable needs to be injected. Without it, the application won’t be able to connect to Fauna. You’ll provide this environment variable when you launch the app.

      Now add the the /signup route to the main.py file. This will create new documents in the Users collection:

      main.py

      @app.route('/signup', methods=['POST'])
      def signup():
      
          body = request.json
          client = FaunaClient(secret=FAUNA_SECRET)
      
          try:
              result = client.query(
                  q.create(
                      q.collection("Users"),
                      {
                          "data": {
                              "username": body["username"]
                          },
                          "credentials": {
                              "password": body["password"]
                          }
                      }
                  )
              )
      
              return {
                  "userId": result['ref'].id()
              }
      
          except faunadb.errors.BadRequest as exception:
              error = exception.errors[0]
              return {
                  "code": error.code,
                  "description": error.description
              }, 409
      

      Note that the Fauna client is being instantiated on every request using the server secret:

      main.py

      ...
      client = FaunaClient(secret=FAUNA_SECRET)
      ...
      

      Once users are logged in, the API will execute queries on behalf of each user using different secrets, which is why it makes sense to instantiate the client on every request.

      Unlike other databases, the Fauna client does not maintain a persistent connection. From the outside world, Fauna behaves like an API; every query is a single HTTP request.

      After the client is ready, the FQL query executes, which creates a new document in the Users collection. Each Fauna driver translates idiomatic syntax to FQL statements. In this route, you added this query:

      main.py

      ...
      q.create(
          q.collection("Users"),
          {
              "data": {
                  "user": json["user"]
              },
              "credentials": {
                  "password": json["password"]
              }
          }
      )
      ...
      

      This is what this query would look like in native FQL:

      Create(
          Collection("Users"),
          {
              "data": {
                  "user": "sammy"
              },
              "credentials": {
                  "password": "secretpassword"
              }
          }
      )
      

      In addition to the document data, you’re adding a credentials configuration with the user’s password. This part of the document is completely private. You will never be able to read a document’s credentials afterwards. When using Fauna’s authentication system, it’s not possible to expose users’ passwords by mistake.

      Finally, if there’s already a user with the same username, a faunadb.errors.BadRequest exception will be raised, and a 409 response with the error information will be returned to the client.

      Next, add the /login route in the main.py file to authenticate the user and password. This follows a similar pattern as the previous example; you execute a query using the Fauna connection and if the authentication fails, you raise a faunadb.errors.BadRequest exception and return a a 401 response with the error information. Add this code to main.py:

      main.py

      @app.route('/login', methods=['POST'])
      def login():
      
          body = request.json
          client = FaunaClient(secret=FAUNA_SECRET)
      
          try:
              result = client.query(
                  q.login(
                      q.match(
                          q.index("Users_by_username"),
                          body["username"]
                      ),
                      {"password": body["password"]}
                  )
              )
      
              return {
                  "secret": result['secret']
              }
      
          except faunadb.errors.BadRequest as exception:
              error = exception.errors[0]
              return {
                  "code": error.code,
                  "description": error.description
              }, 401
      

      This is the FQL query used to authenticate users with Fauna:

      main.py

      q.login(
          q.match(
              q.index("Users_by_username"),
              body["username"]
          ),
          {"password": body["password"]}
      )
      

      This is what this query would look like in native FQL:

      Login(
          Match(
              Index("Users_by_username"),
              "sammy"
          ),
          {"password": "secretpassword"}
      )
      

      Match returns a reference to a document using the Users_by_username index that we created previously.

      If the provided password matches the referenced document, Login will create a new token and return a dictionary with the following keys:

      • ref with a reference to the token for the new document.
      • ts with the timestamp of the transaction.
      • instance with a reference to the document that was used to do the authentication.
      • secret with the token’s secret that will be used to make further queries to Fauna.

      If you run that FQL query into your Fauna dashboard’s shell you will see something similar to this:

      {
        ref: Ref(Ref("tokens"), "292001047221633538"),
        ts: 1614732749110000,
        instance: Ref(Collection("Users"), "291901454585692675"),
        secret: "fnEEDWVnxbACAgQNBIxMIAIIKq1E5xvPPdGwQ_zUFH4F5Dl0neg"
      }
      

      Depending on the security requirements of the project, you have to decide how to handle the token’s secret. If this API was meant to be consumed by browsers, you might return the secret inside a secure cookie or an encrypted JSON Web Token (JWT). Or you might store it as session data somewhere else, like a Redis instance. For the purpose of this demo, you return it in the body of the HTTP response:

      Finally, add this bit of code to main.py, which will start the Flask application:

      main.py

      app.run(host=os.getenv('IP', '0.0.0.0'), port=int(os.getenv('PORT', 8080)))
      

      It’s important to specify the 0.0.0.0 address. Once deployed to the cloud, this application will run in a Docker container. It won’t be able to receive requests from remote clients if it is running on 127.0.0.1, which is the default address for Flask applications.

      This is the complete main.py file so far:

      main.py

      import os
      FAUNA_SECRET = os.environ.get('FAUNA_SECRET')
      
      import flask
      from flask import request
      
      import faunadb
      from faunadb import query as q
      from faunadb.client import FaunaClient
      
      app = flask.Flask(__name__)
      app.config["DEBUG"] = True
      
      @app.route('/signup', methods=['POST'])
      def signup():
      
          body = request.json
          client = FaunaClient(secret=FAUNA_SECRET)
      
          try:
              result = client.query(
                  q.create(
                      q.collection("Users"),
                      {
                          "data": {
                              "username": body["username"]
                          },
                          "credentials": {
                              "password": body["password"]
                          }
                      }
                  )
              )
      
              return {
                  "userId": result['ref'].id()
              }
      
          except faunadb.errors.BadRequest as exception:
              error = exception.errors[0]
              return {
                  "code": error.code,
                  "description": error.description
              }, 409
      
      @app.route('/login', methods=['POST'])
      def login():
      
          body = request.json
          client = FaunaClient(secret=FAUNA_SECRET)
      
          try:
              result = client.query(
                  q.login(
                      q.match(
                          q.index("Users_by_username"),
                          body["username"]
                      ),
                      {"password": body["password"]}
                  )
              )
      
              return {
                  "secret": result['secret']
              }
      
          except faunadb.errors.BadRequest as exception:
              error = exception.errors[0]
              return {
                  "code": error.code,
                  "description": error.description
              }, 401
      
      app.run(host=os.getenv('IP', '0.0.0.0'), port=int(os.getenv('PORT', 8080)))
      

      Save the file.

      To launch this server locally from your terminal, use the following command with the FAUNA_SECRET environment variable with the secret you obtained when creating the server key:

      • FAUNA_SECRET=your_fauna_server_secret python main.py

      After triggering that command, Flask will show a warning informing you it is running with a development WSGI server. This is fine for the purpose of this demo so you can safely ignore this warning.

      Test your API by making HTTP requests using the curl command. Open a new terminal window and run the following command:

      Create a user with the following command:

      • curl -i -d '{"user":"sammy", "password": "secretpassword"}' -H 'Content-Type: application/json' -X POST http://0.0.0.0:8080/signup

      You’ll see the following response, indicating a successful user creation:

      HTTP/1.0 200 OK
      Content-Type: application/json
      Content-Length: 37
      Server: Werkzeug/1.0.1 Python/3.9.2
      Date: Thu, 04 Mar 2021 01:00:47 GMT
      
      {
        "userId": "292092166117786112"
      }
      

      Now authenticate that user with this command:

      • curl -i -d '{"user":"sammy", "password": "secretpassword"}' -H 'Content-Type: application/json' -X POST http://0.0.0.0:8080/login

      You’ll get this successful response:

      HTTP/1.0 200 OK
      Content-Type: application/json
      Content-Length: 70
      Server: Werkzeug/1.0.1 Python/3.9.2
      Date: Thu, 04 Mar 2021 01:01:19 GMT
      
      {
        "secret": "fnEEDbhO3jACAAQNBIxMIAIIOlDxujk-VJShnnhkZkCUPKIHxbc"
      }
      

      Close the terminal window where you ran your curl commands and switch back to the terminal where your Python server is running. Stop your server by pressing CTRL+C.

      Now that the application is working, we’re going to add a private endpoint that requires users to be authenticated.

      Step 4 — Adding a Private Endpoint

      In this step, you’ll add a private endpoint to the API, which will require the user to be authenticated first.

      First, create a new route in the main.py file. This route will respond to the /things endpoint. Place it above the line that starts the server with the app.run() method:

      main.py

      @app.route('/things', methods=['GET'])
      def things():
      

      Next, in the /things route, instantiate the Fauna client:

      main.py

          userSecret = request.headers.get('fauna-user-secret')
          client = FaunaClient(secret=userSecret)
      

      Instead of using the server secret, this route is using the user’s secret from the fauna-user-secret HTTP header which is used to instantiate the Fauna client. By using the users’ secrets instead of the server secret, FQL queries will now be subject to the authorization rules we’ve configured previously in the dashboard.

      Then add this try block to the route to execute the query:

      main.py

          try:
              result = client.query(
                  q.map_(
                      q.lambda_("ref", q.get(q.var("ref"))),
                      q.paginate(q.documents(q.collection("Things")))
                  )
              )
      
              things = map(
                  lambda doc: {
                      "id": doc["ref"].id(),
                      "name": doc["data"]["name"],
                      "color": doc["data"]["color"]
                  },
                  result["data"]
              )
      
              return {
                  "things": list(things)
              }
      

      This executes an FQL query and parses the Fauna response into a serializable type that is then returned as a JSON string in the body of the HTTP response.

      Finally, add this except block to the route:

      main.py

          except faunadb.errors.Unauthorized as exception:
              error = exception.errors[0]
              return {
                  "code": error.code,
                  "description": error.description
              }, 401
      

      If the request doesn’t contain a valid secret, a faunadb.errors.Unauthorized exception will be raised and a 401 response with the error information will be returned.

      This is the full code for the /things route:

      main.py

      @app.route('/things', methods=['GET'])
      def things():
      
          userSecret = request.headers.get('fauna-user-secret')
          client = FaunaClient(secret=userSecret)
      
          try:
              result = client.query(
                  q.map_(
                      q.lambda_("ref", q.get(q.var("ref"))),
                      q.paginate(q.documents(q.collection("Things")))
                  )
              )
      
              things = map(
                  lambda doc: {
                      "id": doc["ref"].id(),
                      "name": doc["data"]["name"],
                      "color": doc["data"]["color"]
                  },
                  result["data"]
              )
      
              return {
                  "things": list(things)
              }
      
          except faunadb.errors.Unauthorized as exception:
              error = exception.errors[0]
              return {
                  "code": error.code,
                  "description": error.description
              }, 401
      

      Save the file and run your server again:

      • FAUNA_SECRET=your_fauna_server_secret python main.py

      To test this endpoint, first obtain a secret by authenticating with valid credentials. Open a new terminal window and execute this curl command:

      • curl -i -d '{"username":"sammy", "password": "secretpassword"}' -H 'Content-Type: application/json' -X POST http://0.0.0.0:8080/login

      This command returns a succesful response, although the value for secret will be different:

      HTTP/1.0 200 OK
      Content-Type: application/json
      Content-Length: 70
      Server: Werkzeug/1.0.1 Python/3.9.2
      Date: Thu, 04 Mar 2021 01:01:19 GMT
      
      {
        "secret": "fnEEDb...."
      }
      

      Now hen do a GET request to /things using the secret:

      curl -i -H 'fauna-user-secret: fnEEDb...' -X GET http://0.0.0.0:8080/things
      

      You’ll get another successful response:

      HTTP/1.0 200 OK
      Content-Type: application/json
      Content-Length: 118
      Server: Werkzeug/1.0.1 Python/3.9.2
      Date: Thu, 04 Mar 2021 01:14:49 GMT
      
      {
        "things": [
          {
            "color": "Yellow",
            "id": "292079274901373446",
            "name": "Banana"
          }
        ]
      }
      

      Close your terminal window where you ran the curl commands. Return to your window where your server is running and stop the server with CTRL+C.

      Now that you have a working app, you’re ready to deploy it.

      Step 4 — Deploying to DigitalOcean

      In the final step of this tutorial, you will create an app on App Platform and deploy it from a GitHub repository.

      Before pushing the project to a Git repository, be sure to run the following command in the project’s folder:

      • pip freeze > requirements.txt

      This will create a requirements.txt file with the list of dependencies that need to be installed once the application is deployed.

      Now initialize your project directory as a Git repository:

      Now execute the following command to add files to your repository:

      This adds all the files in the current directory.

      With the files added, make your initial commit:

      • git commit -m "Initial version of the site"

      Your files will commit.

      Open your browser and navigate to GitHub, log in with your profile, and create a new repository called sharkopedia. Create an empty repository without a README or license file.

      Once you’ve created the repository, return to the command line to push your local files to GitHub.

      First, add GitHub as a remote repository:

      • git remote add origin https://github.com/your_username/sharkopedia

      Next, rename the default branch main, to match what GitHub expects:

      Finally, push your main branch to GitHub’s main branch:

      Your files will transfer. You’re now ready to deploy your app.

      Note: To be able to create an app on App Platform, you’ll first need to add a payment method to your DigitalOcean account.

      The application will run on a container which costs $5 per month, although only a few cents will be needed to test it out. Don’t forget to delete the application once you’re done or you’ll continue to be charged.

      Go to the Apps section of the DigitalOcean dashboard, and click on Launch Your App:

      Select the source for deployment. You will need to authorize DigitalOcean to read your Github repositories. Once you’ve authorized access, select the repository with your Python project and the branch that contains the version of the app you want to deploy:

      Selecting a repository and branch

      At this point, App Platform will determine that your project uses Python and will let you configure some application options:

      Configuring the app options

      Set the following options

      • Ensure the Type is Web Service.
      • Create aFAUNA_SECRET environment variable with your server secret.
      • Set the Run Command to python main.py.
      • Set the HTTP Port to 8080.

      Next, enter a name for your app and select a deploy region:

      Configuring the name of the app and deploy region

      Next, choose the Basic plan and Basic Size that costs $5 per month:

      Selecting the app plan

      After that, scroll down and click on Launch Your App.

      Once you’ve finished configuring the app, a container will be created and deployed with your application. This first-time initialization will take a couple of minutes, but subsequent deploys will be much faster.

      In the app’s dashboard you’ll see a green check mark to indicate the deploy process has finished successfully:

      App is running

      You will now be able to execute HTTP requests to the provided app domain. Execute the following command in your terminal, substituting your_app_name with your actual app name, to return a new secret for the sammy user:

      • curl -i -d '{"user":"sammy", "password": "secretpassword"}' -H 'Content-Type: application/json' -X POST https://your_app_name.ondigitalocean.app/login

      You’ll receive a response similar to the following:

      HTTP/1.0 200 OK
      Content-Type: application/json
      Content-Length: 70
      Server: Werkzeug/1.0.1 Python/3.9.2
      Date: Thu, 04 Mar 2021 01:01:19 GMT
      
      {
        "secret": "fnAADbhO3jACEEQNBIxMIAOOIlDxujk-VJShnnhkZkCUPKIskdjfh"
      }
      

      Your application is now up and running on Digital Ocean.

      Conclusion

      In this tutorial you created a Python REST API using Fauna as the data layer, and you deployed it to DigitalOcean App Platform.

      To keep learning about Fauna and dive deeper into FQL, check out the Fauna Documentation.



      Source link

      Building a Discord Bot in Python


      How to Join

      This Tech Talk is free and open to everyone. Register below to get a link to join the live stream or receive the video recording after it airs.

      DateTimeRSVP
      September 8, 202111 a.m.–12 p.m. ET / 3–4 p.m. GMT

      About the Talk

      Discord is becoming an ever more popular tool for open source communities to connect. Discord isn’t just a great chat and voice app, it also has a rich ecosystem for extending and building bots. Get an overview of the Discord Python library, how Discord handles events, and build your first Discord bot!

      What You’ll Learn

      How to build and deploy your very own Discord bot

      This Talk Is Designed For

      Developers who want to build discord bots

      Resources

      Discord Developer Documentation
      Discord API Documentation
      DigitalOcean Droplets + Docs
      DigitalOcean App Platform + Docs

      To join the live Tech Talk, register here.



      Source link

      How To Install Python 3 and Set Up a Local Programming Environment on Ubuntu 20.04


      Introduction

      Python is a flexible and versatile programming language that can be leveraged for many use cases, with strengths in scripting, automation, data analysis, machine learning, and back-end development. First published in 1991 with a name inspired by the British comedy group Monty Python, the development team wanted to make Python a language that was fun to use. Quick to set up, and written in a relatively straightforward style with immediate feedback on errors, Python is a great choice for beginners and experienced developers alike. Python 3 is the most current version of the language and is considered to be the future of Python.

      This tutorial will guide you through installing Python 3 on your local Linux machine and setting up a programming environment via the command line. This tutorial will explicitly cover the installation procedures for Ubuntu 20.04, but the general principles apply to any other distribution of Debian Linux.

      Prerequisites

      You will need a computer or virtual machine with Ubuntu 20.04 installed, as well as have administrative access to that machine and an internet connection. You can download this operating system via the Ubuntu 20.04 releases page.

      Step 1 — Setting Up Python 3

      We’ll be completing our installation and setup on the command line, which is a non-graphical way to interact with your computer. That is, instead of clicking on buttons, you’ll be typing in text and receiving feedback from your computer through text as well.

      The command line, also known as a shell or terminal, can help you modify and automate many of the tasks you do on a computer every day, and is an essential tool for software developers. There are many terminal commands to learn that can enable you to do more powerful things. The article “An Introduction to the Linux Terminal” can get you better oriented with the terminal.

      On Ubuntu 20.04, you can find the Terminal application by clicking on the Ubuntu icon in the upper-left hand corner of your screen and typing “terminal” into the search bar. Click on the Terminal application icon to open it. Alternatively, you can hit the CTRL, ALT, and T keys on your keyboard at the same time to open the Terminal application automatically.

      Ubuntu Terminal

      Ubuntu 20.04 ships with both Python 3 and Python 2 pre-installed. To make sure that our versions are up-to-date, let’s update and upgrade the system with the apt command to work with Ubuntu’s Advanced Packaging Tool:

      • sudo apt update
      • sudo apt -y upgrade

      The -y flag will confirm that we are agreeing that all items to be installed, but depending on your version of Linux, you may need to confirm additional prompts as your system updates and upgrades.

      Once the process is complete, we can check the version of Python 3 that is installed in the system by typing:

      You will receive output in the terminal window that will let you know the version number. The version number may vary, but it will be similar to this:

      Output

      Python 3.8.10

      To manage software packages for Python, let’s install pip, a tool that will install and manage programming packages we may want to use in our development projects. You can learn more about modules or packages that you can install with pip by reading “How To Import Modules in Python 3.”

      • sudo apt install -y python3-pip

      Python packages can be installed by typing:

      • pip3 install package_name

      Here, package_name can refer to any Python package or library, such as Django for web development or NumPy for scientific computing. So if you would like to install NumPy, you can do so with the command pip3 install numpy.

      There are a few more packages and development tools to install to ensure that we have a robust set-up for our programming environment:

      • sudo apt install build-essential libssl-dev libffi-dev python-dev

      Press y if prompted to do so.

      Once Python is set up, and pip and other tools are installed, we can set up a virtual environment for our development projects.

      Step 2 — Setting Up a Virtual Environment

      Virtual environments enable you to have an isolated space on your computer for Python projects, ensuring that each of your projects can have its own set of dependencies that won’t disrupt any of your other projects.

      Setting up a programming environment provides us with greater control over our Python projects and over how different versions of packages are handled. This is especially important when working with third-party packages.

      You can set up as many Python programming environments as you want. Each environment is basically a directory or folder in your computer that has a few scripts in it to make it act as an environment.

      While there are a few ways to achieve a programming environment in Python, we’ll be using the venv module here, which is part of the standard Python 3 library. Let’s install venv by typing:

      • sudo apt install -y python3-venv

      With this installed, we are ready to create environments. Let’s either choose which directory we would like to put our Python programming environments in, or create a new directory with mkdir, as in:

      • mkdir environments
      • cd environments

      Once you are in the directory where you would like the environments to live, you can create an environment by running the following command:

      Essentially, this sets up a new directory that contains a few items which we can view with the ls command:

      Output

      bin include lib lib64 pyvenv.cfg share

      Together, these files work to make sure that your projects are isolated from the broader context of your local machine, so that system files and project files don’t mix. This is good practice for version control and to ensure that each of your projects has access to the particular packages that it needs. Python Wheels, a built-package format for Python that can speed up your software production by reducing the number of times you need to compile, will be in the Ubuntu 18.04 share directory.

      To use this environment, you need to activate it, which you can do by typing the following command that calls the activate script:

      • source my_env/bin/activate

      Your prompt will now be prefixed with the name of your environment, in this case it is called my_env. Your prefix may appear somewhat differently, but the name of your environment in parentheses should be the first thing you see on your line:

      This prefix lets us know that the environment my_env is currently active, meaning that when we create programs here they will use only this particular environment’s settings and packages.

      Note: Within the virtual environment, you can use the command python instead of python3, and pip instead of pip3 if you would prefer. If you use Python 3 on your machine outside of an environment, you will need to use the python3 and pip3 commands exclusively.

      After following these steps, your virtual environment is ready to use.

      Step 3 — Creating a “Hello, World” Program

      Now that we have our virtual environment set up, let’s create a traditional “Hello, World!” program. This will let us test our environment and provides us with the opportunity to become more familiar with Python if we aren’t already.

      To do this, we’ll open up a command-line text editor such as nano and create a new file:

      When the text file opens up in the terminal window we’ll type out our program:

      print("Hello, World!")
      

      Exit nano by typing the CTRL and X keys, and when prompted to save the file press y.

      Once you exit out of nano and return to your shell, we’ll run the program:

      The hello.py program that you created should cause your terminal to produce the following output:

      Output

      Hello, World!

      To leave the environment, type the command deactivate and you will return to your original directory.

      Conclusion

      Congratulations! At this point you have a Python 3 programming environment set up on your local Ubuntu machine and can begin a coding project!

      If you are using a different local machine, refer to the tutorial that is relevant to your operating system in our “How To Install and Set Up a Local Programming Environment for Python 3” series. Alternatively, if you’re using an Ubuntu server, you can follow the “How To Install Python and Set Up a Programming Environment on an Ubuntu 20.04 Server” tutorial.

      With your local machine ready for software development, you can continue to learn more about coding in Python by reading our free How To Code in Python 3 eBook, or consulting our Programming Project tutorials.



      Source link