<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: James Kinga</title>
    <description>The latest articles on DEV Community by James Kinga (@james_kinga).</description>
    <link>https://dev.to/james_kinga</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F700499%2F50ae9bb6-b0b2-4bbc-8d67-6f2235cb83ae.png</url>
      <title>DEV Community: James Kinga</title>
      <link>https://dev.to/james_kinga</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/james_kinga"/>
    <language>en</language>
    <item>
      <title>Python3: Try-Else Statement</title>
      <dc:creator>James Kinga</dc:creator>
      <pubDate>Thu, 13 Apr 2023 18:55:39 +0000</pubDate>
      <link>https://dev.to/james_kinga/python3-try-else-statement-5135</link>
      <guid>https://dev.to/james_kinga/python3-try-else-statement-5135</guid>
      <description>&lt;h3&gt;
  
  
  Table of contents
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Introduction
What is Try-Else Statement?
Benefits of try-else
Conclusion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Errors are common in programming, regardless of the level of experience and competence. These errors are often referred to as exceptions and occur due to many reasons such as unexpected user inputs, network failures, system crashes, etc. In Python, exceptions are handled using the try-except statement. However, there is another useful variation of the try statement called the try-else statement, which we will be discussing in this article.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Try-Else Statement?
&lt;/h3&gt;

&lt;p&gt;The try-else statement in Python is used to execute a block of code if no exception is thrown in the try block. It is an optional clause that can be added to the end of a try-except statement. The syntax of the try-else statement is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;try:
    # a block of code that may cause an exception
except ExceptionType:
    # a block of code to handle the exception
else:
    # a block of code that executes if theres no exception raised
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the try block, we write the code that may raise an exception. If an exception is raised, the code in the except block is executed to handle the exception. However, if there is no exception raised in the try block, the code in the else block is executed.&lt;/p&gt;

&lt;p&gt;Let's consider an example to understand the try-else statement better. Assume we want to take input from the user and calculate its square. We can write the code using the try-else statement as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;try:
    x = int(input("Enter a digit: "))
except ValueError:
    print("Invalid input. Please enter another digit.")
else:
    print("The square of the digit is: ", x*x)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code, we use the input() function to take input from the user. However, since the input can be any string, we use the int() function to convert the input into an integer. If the user enters a non-numeric value, a ValueError exception is raised, and the code in the except block is executed, which prints an error message. If the input is a valid integer, the code in the else block is executed, which calculates and prints the square of the number.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of try-else
&lt;/h3&gt;

&lt;p&gt;Now, let's take a look at some benefits of using the try-else statement in Python.&lt;/p&gt;

&lt;ol&gt;
  &lt;li rel="tab1"&gt;Improved code readability&lt;/li&gt;
  &lt;li rel="tab2"&gt;Better error handling&lt;/li&gt;
  &lt;li rel="tab3"&gt;Improved code readability&lt;/li&gt;
&lt;/ol&gt;


&lt;h3 rel="tab1"&gt;1. Improved code readability&lt;/h3&gt;

&lt;p&gt;The try-else statement can help make your code more readable and easier to understand. By separating the code that may raise an exception from the code that executes when there is no exception, you can make it clear what your code is doing and how it handles errors.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     try:
        f = open('file.txt', 'r')
        contents = f.read()
        print(contects)
     except IOError:
        print("File not found or could not be read.")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This code opens a file, reads its contents, and prints them. However, if the file does not exist or could not be read, the code in the except block is executed, which prints an error message.&lt;/p&gt;

&lt;p&gt;Now, let's rewrite the code using the try-else statement:&lt;br&gt;
   &lt;/p&gt;
&lt;br&gt;
   &lt;pre&gt;&lt;code&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     try:
        f = open('file.txt', 'r')
     except IOError:
        print("File not found or could not be read.")
     else:
        contents = f.read()
        print(contects)
&lt;/code&gt;&lt;/pre&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;br&gt;
   

&lt;p&gt;In this code, we use the try-else statement to separate the code that may raise an exception from the code that executes when there is no exception. The code in the try block attempts to open the file, and if there is an IOError, the code in the except block is executed. If the file is successfully opened, the code in the else block is executed, which reads the file's contents and prints them. This code is more readable and easier to understand than the previous code.&lt;/p&gt;


&lt;h3 rel="tab2"&gt;2. Better error handling&lt;/h3&gt;

&lt;p&gt;The try-else statement can also help you handle errors more effectively. By separating the code that may raise an exception from the code that executes when there is no exception, you can handle errors more precisely and avoid catching and handling exceptions that are not relevant to the current code.&lt;/p&gt;

&lt;p&gt;For example, consider the code below:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     try:
        result = calculate_result()
     except Exception:
        print("An error occurred. Please try again later.")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this code, we are catching all exceptions that may occur while calling the &lt;code&gt;calculate_result()&lt;/code&gt; function. This may include exceptions that are not related to the function's logic, such as network errors or system crashes. By catching all exceptions, we are not handling errors precisely and may hide important error messages.&lt;/p&gt;

&lt;p&gt;Now, let's rewrite the code using the try-else statement:&lt;/p&gt;


&lt;br&gt;
   &lt;pre&gt;&lt;code&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    try:
       result = calculate_result()
    except ValueError:
       print("Invalid input. Please enter a valid number.")
    except ZeroDivisionError:
       print("Cannot divide by zero.")
    else:
       print("The result is:", result)
&lt;/code&gt;&lt;/pre&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;br&gt;
   

&lt;p&gt;In this code, we use the try-else statement to handle specific exceptions that may occur while calling the calculate_result() function. If the function raises a ValueError, we print an error message indicating that the input was invalid. If the function raises a ZeroDivisionError, we print an error message indicating that the input was zero, and division by zero is not allowed. If there is no exception raised, we print the result. This code handles errors more precisely and provides better feedback to the user.&lt;/p&gt;


&lt;h3 rel="tab3"&gt;3. Cleaner code&lt;/h3&gt;

&lt;p&gt;The try-else statement can help you write cleaner code by eliminating unnecessary code blocks and reducing the nesting level of your code. By separating the code that may raise an exception from the code that executes when there is no exception, you can write cleaner and more concise code.&lt;/p&gt;

&lt;p&gt;For example, consider the following code:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    try:
       x = int(input("Enter a number: "))
    except ValueError:
       print("Invalid input. Please enter a valid number.")
    else:
       try:
          result = 100/x
       except ZeroDivisionError:
          print("Cannot divide by zero.")
       else:
          print("The result is:", result)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In this code, we use two nested try-except statements to handle different types of exceptions. The outer try-except statement handles the &lt;code&gt;ValueError&lt;/code&gt; exception that may occur while converting the input to an integer. The inner try-except statement handles the ZeroDivisionError exception that may occur while dividing 100 by the input. This code is more complex and harder to read than the previous code.&lt;/p&gt;

&lt;p&gt;Now, let's rewrite the code using the try-else statement:&lt;/p&gt;


&lt;br&gt;
   &lt;pre&gt;&lt;code&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    try:
       x = int(input("Enter a number: "))
    except ValueError:
       print("Invalid input. Please enter a valid number.")
    else:
       if x == 0:
          print("Cannot divide by zero.")
       else:
          result = 100/x
          print("The result is:", result)
&lt;/code&gt;&lt;/pre&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;br&gt;
   

&lt;p&gt;In this code, we use the try-else statement to handle the input conversion and the division in a single block of code. If the input is zero, we print an error message. If the input is valid, we calculate the result and print it. This code is cleaner and easier to read than the previous code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In conclusion, the try-else statement in Python is a useful variation of the try-except statement that can help you write cleaner, more readable, and more effective code. By separating the code that may raise an exception from the code that executes when there is no exception, you can handle errors more precisely, provide better feedback to the user, and write cleaner and more concise.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Simple Twitter Bot to Retweet &amp; Favorite Using Python &amp; Tweepy</title>
      <dc:creator>James Kinga</dc:creator>
      <pubDate>Mon, 14 Feb 2022 12:07:24 +0000</pubDate>
      <link>https://dev.to/james_kinga/simple-twitter-bot-to-retweet-favorite-using-python-tweepy-50bg</link>
      <guid>https://dev.to/james_kinga/simple-twitter-bot-to-retweet-favorite-using-python-tweepy-50bg</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I came across the #TwitterBotChallengeKE while scrolling through Twitter's great tech communities. As a genuinely curious individual, I decided to give it a try. After a few google searches, I discovered quite a few resources and at least got a clue on where to start. This is a great way to test and flex your coding skills, while interacting with APIs and learning how they work. It's also fascinating to see what you build in action, especially if you're not very active on Twitter. There's a rich pool of resources from around the web and a supportive Twitter Community making it beginner friendly for all codenewbies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Twitter Bot Challenge (#BuildWhat'sNext)
&lt;/h2&gt;

&lt;p&gt;The Twitter Bot Challenge aims to support the tech ecosystem in Kenya to build using the Twitter API. We will be using the API to build for fun by creating bots. This is a summary of my experience participating, the good, the bad and the ugly, and most of all what you learned.&lt;/p&gt;

&lt;p&gt;The goal is to create a twitter bot which tweets Dev, Linux, and other Coding content. Primarily, I decided to develop the bot using Python as it has several handy libraries and tools. As always, it is safer to code new python projects within virtual environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Twitter developer account&lt;/li&gt;
&lt;li&gt;Python3.8&lt;/li&gt;
&lt;li&gt;Python virtual environment&lt;/li&gt;
&lt;li&gt;Hosting Server or Cloud&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Twitter Developer Account
&lt;/h2&gt;

&lt;p&gt;Create a Twitter developer account. I decided to play it safe and create a separate account from my main Twitter account (&lt;a href="https://twitter.com/Kingah254" rel="noopener noreferrer"&gt;@Kingah254&lt;/a&gt;). I’ve had a few accounts suspended in the past, I had to be cautious. This is a fairly easy processes and approval takes a few minutes.&lt;/p&gt;

&lt;p&gt;Search for Twitter Developer Account on any search engine of your choice and choose the first option (should be). This will redirect you to a Developer Portal. Create a new application under the &lt;strong&gt;Projects &amp;amp; Apps&lt;/strong&gt; section. &lt;/p&gt;

&lt;p&gt;Request for a Twitter Developer Account and provide a few answers:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgw3sb6fd05jnjeydjwc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgw3sb6fd05jnjeydjwc.png" alt="First page you'll be greeted with" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create an application:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljyunblbr296sc0bg7xr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fljyunblbr296sc0bg7xr.png" alt="Projects and Applications" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Request for privileged permissions under the User Authentication Settings. I decided to use OAuth 1.0a:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxh4kmjmfxmh00ha0jeua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxh4kmjmfxmh00ha0jeua.png" alt="User Authentication settings" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the Read and write and Direct message App permissions:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxrye3rzh7z9d4e71jkk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxrye3rzh7z9d4e71jkk.png" alt="Permissions" width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Generate API Key, API Key Secret, Access Token and Access Token Secret:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufh8pz07p102shovnbgt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufh8pz07p102shovnbgt.png" alt="Generate and copy keys" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Python Virtual Environment
&lt;/h2&gt;

&lt;p&gt;For this project, we will use Python3.8, and primarily the Tweepy Python package to develop a simple Twitter bot that retweets, and favorites tweets with certain keywords. &lt;/p&gt;

&lt;p&gt;Create a virtual environment to install all the necessary modules using pip, separate and without interfering with the system(global) packages. This can be done by running the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 -m venv yourvirtualenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Activate the virtual environment to install the libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source yourvirtualenv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the following packages/libraries:&lt;/p&gt;

&lt;p&gt;tweepy - this is the primary python package the bot uses to communicate or interface with the Twitter API. It has a rich module and function libraries in addition to a supportive community. This makes it the most popular package for automating Twitter.&lt;/p&gt;

&lt;p&gt;Install using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install tweepy

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;configparser - used to hide important credentials such as api key, api key secret, access token and access token secret. Therefore, it is safer when sharing the code with others as one does not have to share these credentials.&lt;/p&gt;

&lt;p&gt;Install using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install configparser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;time - a Python module that is used to represent time in different ways including objects, numbers and strings as well as offering various functionality such as waiting during code execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Code
&lt;/h2&gt;

&lt;p&gt;Create a configuration file, &lt;code&gt;config.ini&lt;/code&gt; to store the authentication credentials i.e. the API keys and access tokens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In config.ini

[jk_bot]
api_key=&amp;lt;Your API Key here&amp;gt;
api_key_secret=&amp;lt;Your API Key Secret Here&amp;gt;

access_token=&amp;lt;Your Access Token Here&amp;gt;
access_token_secret=&amp;lt;Your Access Token Secret here&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frj8guumx3fuxt2o1681m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frj8guumx3fuxt2o1681m.png" alt="The Config.ini file" width="440" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ll start by importing the dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import tweepy
import configparser
from time import sleep

#ConfigParser is used to grab the authentication credentials from a config 
#file making it safer when sharing the code.
config = configparser.ConfigParser()
config.read('config.ini')

apiKey = config['jk_bot']['apiKey']
apiKeySecret = config['jk_bot']['apiKeySecret']

accessToken = config['jk_bot']['accessToken']
accessTokenSecret = config['jk_bot']['accessTokenSecret']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we will instantiate the authentiacation handler using the API key and API key secret and then use the access token and access token secret to complete the authentication process on the API authentication handler. Afterwards, we instantiate a new tweepy API object using the authentication handler object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import tweepy
import configparser
from time import sleep

#ConfigParser is used to grab the authentication credentials from a config 
#file making it safer when sharing the code.
config = configparser.ConfigParser()
config.read('config.ini')

apiKey = config['jk_bot']['apiKey']
apiKeySecret = config['jk_bot']['apiKeySecret']

accessToken = config['jk_bot']['accessToken']
accessTokenSecret = config['jk_bot']['accessTokenSecret']

# authenticate API keys 
auth = tweepy.OAuthHandler(apiKey, apiKeySecret)
auth.set_access_token(accessToken, accessTokenSecret)
print('Authentication successful!')

api = tweepy.API(auth)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code should return an Authentication Successful! message &lt;/p&gt;

&lt;p&gt;Next, assign favorite and follow and create a list of the keywords to react by to tweets. After which we create a function using tweepy cursor and search to get the tweets and the usernames. The main function also defines the logic of actions for the bot. If the bot has not retweeted a certain tweet, favorite and retweet it using the favorite() and retweet() methods available to the tweet object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import tweepy
import configparser
from time import sleep

#ConfigParser is used to grab the authentication credentials from a config 
#file making it safer when sharing the code.
config = configparser.ConfigParser()
config.read('config.ini')

apiKey = config['jk_bot']['apiKey']
apiKeySecret = config['jk_bot']['apiKeySecret']

accessToken = config['jk_bot']['accessToken']
accessTokenSecret = config['jk_bot']['accessTokenSecret']

# authenticate API keys 
auth = tweepy.OAuthHandler(apiKey, apiKeySecret)
auth.set_access_token(accessToken, accessTokenSecret)
print('Authentication successful!')

api = tweepy.API(auth)

# assign to favorite and follow
Favorite = True
Follow = True

hashtags = ['#python']

# the function with the logic on the bot actions
def main():
    for tweet in tweepy.Cursor(
        api.search_tweets, q=hashtags).items():
        try:
            print("\nTweet by: @" + tweet.user.screen_name)

            # check if we have retweeted and retweet if not
            if not tweet.retweeted:
                try:
                    tweet.retweet()
                    print("Tweet retweeted!")
                except Exception as e:
                    print(e)

            # check if we have favorited and favorite if not
            if not tweet.favorited:
                try:
                    tweet.favorite()
                    print("Tweet favorited!")
                except Exception as e:
                    print(e)

            # bot sleep time (seconds)
            sleep(60)

        except tweepy.TweepyError as e:
            print(e.reason)


        except StopIteration:
            break


while True:
    main()
    sleep(20)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once completed, we can run the bot. Here is a screen capture of the bot in action:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhxd5ylmko5200lxghou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzhxd5ylmko5200lxghou.png" alt="The output" width="800" height="825"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This is a simple Twitter bot and there is a lot one can do using Tweepy. It is possible to add more logic using several other methods to implement more functionalities.&lt;br&gt;
Next goal is to host the bot on the cloud to ensure it runs throughout. Follow for a follow-up article. &lt;/p&gt;

</description>
      <category>python</category>
      <category>linux</category>
      <category>twitter</category>
      <category>coding</category>
    </item>
    <item>
      <title>Important Network and Troubleshooting Tools for Linux</title>
      <dc:creator>James Kinga</dc:creator>
      <pubDate>Wed, 29 Dec 2021 09:05:16 +0000</pubDate>
      <link>https://dev.to/james_kinga/important-network-and-troubleshooting-tools-for-linux-l7k</link>
      <guid>https://dev.to/james_kinga/important-network-and-troubleshooting-tools-for-linux-l7k</guid>
      <description>&lt;h2&gt;
  
  
  1. Overview
&lt;/h2&gt;

&lt;p&gt;At times, navigating Linux operating system can be daunting for new users and so is the troubleshooting process. Unlike in Windows where one simply navigates to the control panel to troubleshoot network issues, Linux is often not so direct and obvious. &lt;/p&gt;

&lt;p&gt;Therefore, this article seeks to simplify this process by discussing some of the basic Linux commands to view the network status and troubleshoot any related issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Tools and Commands
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1. ifconfig
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;ifconfig&lt;/strong&gt; displays the status of the currently active interfaces if not argument is given.&lt;br&gt;
Useful options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-a&lt;/code&gt;    to view all interfaces which are currently available, even if down&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-s&lt;/code&gt;     display a short list (like netstat -i)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example of &lt;strong&gt;ifconfig&lt;/strong&gt; output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eth0      Link encap:Ethernet  HWaddr 02:42:ac:11:00:0a  
          inet addr:172.17.0.10  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2235 errors:0 dropped:0 overruns:0 frame:0
          TX packets:667 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:508519 (508.5 KB)  TX bytes:92572 (92.5 KB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;eth0&lt;/strong&gt; - the Ethernet interface. Can be &lt;strong&gt;eth1, eth2,..., ethn&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;lo&lt;/strong&gt; - the loopback interface which is used by the system to communicate with itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.2. ping
&lt;/h3&gt;

&lt;p&gt;Basically used to test connectivity. Common and handy flags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;-c&lt;/strong&gt;, &lt;strong&gt;-count&lt;/strong&gt; &lt;em&gt;count&lt;/em&gt;&lt;br&gt;
Stop after sending (and receiving) &lt;em&gt;count&lt;/em&gt; ECHO_RESPONSE packets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;-q&lt;/strong&gt;, &lt;strong&gt;-quiet&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Quiet output. Nothing is displayed except the summary lines at startup time and when finished.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;-i&lt;/strong&gt;, &lt;strong&gt;-interval&lt;/strong&gt; &lt;em&gt;wait&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Wait &lt;em&gt;wait&lt;/em&gt; seconds &lt;em&gt;between sending each packet&lt;/em&gt;. The default is to wait for one second between each packet. This option is incompatible with the &lt;strong&gt;-f&lt;/strong&gt; option.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2.3. whois
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;whois&lt;/strong&gt; searches for an object in a RFC 3912 (WHOIS) database.&lt;br&gt;
WHOIS is a query and response protocol that is commonly used for accessing databases that contain the registered users of an Internet resource, such as a [domain name] or a [IP] [address] block, but it can also be used for a wider range of information.&lt;/p&gt;

&lt;p&gt;The majority of recent implementations of &lt;strong&gt;whois&lt;/strong&gt; attempt to guess the correct server to query for the requested object. &lt;strong&gt;Whois&lt;/strong&gt; will connect to &lt;strong&gt;&lt;a href="http://whois.networksolutions.com/" rel="noopener noreferrer"&gt;whois.networksolutions.com&lt;/a&gt;&lt;/strong&gt; for NIC handles or &lt;strong&gt;&lt;a href="http://whois.arin.net/" rel="noopener noreferrer"&gt;whois.arin.net&lt;/a&gt;&lt;/strong&gt; for [IPv4] addresses and network names if no guess can be made.&lt;br&gt;
Often not installed by default on most systems but can be installed using apt - &lt;code&gt;sudo apt install whois&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2.4. nslookup
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;nslookup&lt;/strong&gt; is used to determine the Internet name servers interactively. It stands for Name Server Lookup. &lt;br&gt;
&lt;strong&gt;nslookup&lt;/strong&gt; has two modes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Interactive: useful in querying name servers for information about various hosts and domains or to print a list of hosts in a domain.&lt;/li&gt;
&lt;li&gt;Non-interactive: useful to print just the name and requested information for a host or domain.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nslookup [-option] [name | -] [server]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;strong&gt;host [server]&lt;/strong&gt; looks for information for a host using the default server or server, if one is given.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.5. traceroute
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;traceroute&lt;/strong&gt; prints the route packets trace to network host.&lt;br&gt;
Traceroute records the path packets follow from an IP network to a certain host. It makes use of the IP protocol's time to live (TTL) parameter to try to get an ICMP TIME EXCEEDED response from each gateway on the route to the host.&lt;/p&gt;
&lt;h3&gt;
  
  
  2.6. netstat
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;netstat&lt;/strong&gt; gets the network connections, routing tables, interface statistics, masquerade connections, and multicast memberships. &lt;br&gt;
This tool prints information about the Linux subsytem. Useful arguments include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;--route,&lt;/strong&gt; &lt;strong&gt;-r&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Display the kernel routing tables. See the description in &lt;strong&gt;route&lt;/strong&gt;(8) for details.  &lt;strong&gt;netstat&lt;/strong&gt; &lt;strong&gt;-r&lt;/strong&gt; and  &lt;strong&gt;route&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;-e&lt;/strong&gt; produce the same output.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;--groups, -g&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Display multicast group membership information for IPv4 and IPv6.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;--interfaces, -i&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Display a table of all network interfaces.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;--statistics, -s&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Display summary statistics for each protocol.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  2.7. dig
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;dig&lt;/strong&gt; is a DNS lookup tool. This means it interrogates &lt;strong&gt;dig&lt;/strong&gt; is a flexible tool for interrogating DNS name servers. It performs DNS lookups and displays the answers that are returned from the name server(s) that were queried. &lt;/p&gt;

&lt;p&gt;Most DNS administrators use &lt;strong&gt;dig&lt;/strong&gt; to troubleshoot DNS problems because of its flexibility, ease of use and clarity of output. Other lookup tools tend to have less functionality than &lt;strong&gt;dig&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Simple usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dig @server name type

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;server&lt;/strong&gt;&lt;br&gt;
is the name or IP address of the name server to query. When the supplied server argument is a hostname, &lt;strong&gt;dig&lt;/strong&gt; resolves that name before querying that name server.&lt;br&gt;
If no server argument is provided, &lt;strong&gt;dig&lt;/strong&gt; consults /etc/resolv.conf; if an address is found there, it queries the name server at that address. If either of the &lt;strong&gt;-4&lt;/strong&gt; or &lt;strong&gt;-6&lt;/strong&gt; options are in use, then only addresses for the corresponding transport will be tried. If no usable addresses are found, &lt;strong&gt;dig&lt;/strong&gt; will send the query to the local host. The reply from the name server that responds is displayed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;name&lt;/strong&gt;&lt;br&gt;
is the name of the resource record that is to be looked up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;br&gt;
indicates what type of query is required — ANY, A, MX, SIG, etc.  type can be any valid query type. If no type argument is supplied, &lt;strong&gt;dig&lt;/strong&gt; will perform a lookup for an A record.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  3. Conclusion
&lt;/h2&gt;

&lt;p&gt;This article looked at seven handy network tools for Linux: &lt;em&gt;ifconfig&lt;/em&gt;, &lt;em&gt;ping&lt;/em&gt;, &lt;em&gt;whois&lt;/em&gt;, &lt;em&gt;nslookup&lt;/em&gt;, &lt;em&gt;traceroute&lt;/em&gt;, &lt;em&gt;netstat&lt;/em&gt; and &lt;em&gt;dig&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;We also discussed the usage of each tool and its importance in troubleshooting various network issues.&lt;/p&gt;

</description>
      <category>ubuntu</category>
      <category>linux</category>
      <category>performance</category>
      <category>management</category>
    </item>
    <item>
      <title>Getting Started with Docker &amp; Flask</title>
      <dc:creator>James Kinga</dc:creator>
      <pubDate>Sun, 26 Sep 2021 09:53:51 +0000</pubDate>
      <link>https://dev.to/james_kinga/getting-started-with-docker-flask-44i</link>
      <guid>https://dev.to/james_kinga/getting-started-with-docker-flask-44i</guid>
      <description>&lt;p&gt;This article offers a look at how to get started with docker and flask through a practical and hands-on (approach) python application. The goal is to provide a first look and understanding of some of the most quintessential tools for developers in the contemporary world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;

&lt;p&gt;Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly. With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker’s methodologies for shipping, testing, and deploying code quickly, you can significantly reduce the delay between writing code and running it in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker Container
&lt;/h3&gt;

&lt;p&gt;Essentially, a container refers to a unit that houses all the code and dependencies of an application in a standard format that allows it to runs quickly and reliably across computing environments. Therefore, a docker container lightweight, standalone, executable container that comprises all components necessary to run an application such as libraries,code, and runtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker installation
&lt;/h3&gt;

&lt;p&gt;The recommended method of installation is through setting up Docker's repositories and installing from them; it's not only easy to install but also enables quick upgradability. Therefore, we shall install using the repository approach in Ubuntu 20.04 LTS.&lt;/p&gt;

&lt;h4&gt;
  
  
  Set up the repository
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;First, update &lt;code&gt;apt&lt;/code&gt; and install necessary packages to us a repository over HTTPS:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;apt-transport-https &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ca-certificates &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curl &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;gnupg &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;lsb-release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add Docker’s official GPG key:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/ubuntu/gpg | &lt;span class="nb"&gt;sudo &lt;/span&gt;gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/share/keyrings/docker-archive-keyring.gpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Set up a stable repository and add the nightly or test (or both) repository:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="go"&gt;  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
&lt;/span&gt;&lt;span class="gp"&gt;  $&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;lsb_release &lt;span class="nt"&gt;-cs&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; stable&lt;span class="s2"&gt;" | sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Install Docker Engine
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Run an update &lt;code&gt;apt&lt;/code&gt; and install the latest version of Docker Engine and containerd:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;docker-ce docker-ce-cli containerd.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Confirm whether the Docker Engine is correctly installed using &lt;code&gt;hello-world&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can visit the official &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Docker Docs&lt;/a&gt; page to view the installation procedures for other operating systems&lt;/p&gt;

&lt;h2&gt;
  
  
  Flask
&lt;/h2&gt;

&lt;p&gt;This is a simple and lightweight Python web framework that offers useful tools for developing Python web applications.&lt;br&gt;
Flask is super useful for building microservices, you can utilize any number of its built-in extensions to design and deploy microservices at high velocity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Our Environment
&lt;/h2&gt;

&lt;p&gt;This project will require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.6+ and PIP3&lt;/li&gt;
&lt;li&gt;Virtual environment - Venv&lt;/li&gt;
&lt;li&gt;Create project directory&lt;/li&gt;
&lt;li&gt;Create &lt;code&gt;venv&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install required packages using PIP e.g. Flask&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a directory for the app and navigate into the directory:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;demoapp
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;demoapp/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create a virtual environment using &lt;code&gt;venv&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="go"&gt;venv
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Activate the virtual environment:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The prefix &lt;code&gt;(venv)&lt;/code&gt; is an indication that the virtual environment is active.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Flask using &lt;code&gt;pip3&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pip3 &lt;span class="nb"&gt;install &lt;/span&gt;flask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Demo Flask Application
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Build the python application,
&lt;/h3&gt;

&lt;p&gt;This is a simple python application that utilizes the GET and POST requests. It creates a form where a user (say a student), is prompted to enter their name and the field of interest. The user inputs are the formatted and displayed upon clicking the submit button.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create &lt;code&gt;app.py&lt;/code&gt; and code using an IDE of your choice. In this case, we use VS Code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Here is the code for the application:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# import Flask and request
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="c1"&gt;# develop the app
&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# both GET and POST requests
&lt;/span&gt;&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/form-example&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;form_example&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# the POST request
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;interest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;interest&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;
            &amp;lt;h1&amp;gt;The student&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s name is: {}&amp;lt;/h1&amp;gt;
            &amp;lt;h1&amp;gt;The field of interest is: {}&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# the GET request
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;
              &amp;lt;form method=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;
                  &amp;lt;div&amp;gt;&amp;lt;label&amp;gt;Username: &amp;lt;input type=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; name=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&amp;lt;/label&amp;gt;&amp;lt;/div&amp;gt;
                  &amp;lt;div&amp;gt;&amp;lt;label&amp;gt;Interest: &amp;lt;input type=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; name=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;interest&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&amp;lt;/label&amp;gt;&amp;lt;/div&amp;gt;
                  &amp;lt;input type=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;submit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; value=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Submit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;
              &amp;lt;/form&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# we'll run the app in debug mode on port 3000
&lt;/span&gt;    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Generate a &lt;code&gt;requirements.txt&lt;/code&gt; file using &lt;code&gt;freeze&lt;/code&gt; command
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pip freeze &amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build the App's container image
&lt;/h3&gt;

&lt;p&gt;In order to build the application, you need to use a &lt;code&gt;Dockerfile&lt;/code&gt;. A &lt;code&gt;Dockerfile&lt;/code&gt; is simply a text-based script of instructions that is used to create a container image.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a file named &lt;code&gt;Dockerfile&lt;/code&gt; in the same directory as &lt;code&gt;app.py&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;Dockerfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Contents of the Dockerfile:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.6&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /src&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./requirements.txt /src/requirements.txt&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; src&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000:3000&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;pip3 &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "python", "app.py" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Build the container image using &lt;code&gt;docker build&lt;/code&gt; command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; demoapp &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running the application
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Start the container using &lt;code&gt;docker run&lt;/code&gt; command
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker run &lt;span class="nt"&gt;-dp&lt;/span&gt; 3000:3000 demoapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Use your browser to access &lt;code&gt;http://172.17.0.2:3000/form-example&lt;/code&gt;. You should see the app!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;The first page is a form with &lt;strong&gt;Username&lt;/strong&gt; and &lt;strong&gt;Interest&lt;/strong&gt; field entries and a &lt;strong&gt;Submit&lt;/strong&gt; button:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55symdc99shxe1r5jw3t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55symdc99shxe1r5jw3t.png" alt="Screen1" width="587" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upon entering the name, field of interest press &lt;strong&gt;Submit&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F68tunupq6zg3bi3u5zs4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F68tunupq6zg3bi3u5zs4.png" alt="Screen2" width="584" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And Voila!!&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fofsaqryde6lhvqpmytfa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fofsaqryde6lhvqpmytfa.png" alt="Screen3" width="738" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>docker</category>
      <category>flask</category>
    </item>
  </channel>
</rss>
