<?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>Forem: Thomas Montfort</title>
    <description>The latest articles on Forem by Thomas Montfort (@tmontytech).</description>
    <link>https://forem.com/tmontytech</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%2F570527%2F95a8dfc4-f328-4b5f-871e-b3238c283ece.jpg</url>
      <title>Forem: Thomas Montfort</title>
      <link>https://forem.com/tmontytech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/tmontytech"/>
    <language>en</language>
    <item>
      <title>Create an Automated Web Bot with Selenium in Python</title>
      <dc:creator>Thomas Montfort</dc:creator>
      <pubDate>Sat, 08 May 2021 16:16:13 +0000</pubDate>
      <link>https://forem.com/tmontytech/create-an-automated-web-bot-with-selenium-in-python-3hc5</link>
      <guid>https://forem.com/tmontytech/create-an-automated-web-bot-with-selenium-in-python-3hc5</guid>
      <description>&lt;h3&gt;
  
  
  Motivation
&lt;/h3&gt;

&lt;p&gt;Due to the pandemic, a lot of activities require signing up online in advance. At my University’s gym, they offer 2 hour slots throughout the day, each of which open 6 hours in advance for reservation. Because the demand for time slots heavily outweigh the amount of slots, the competition for getting a slot has reached a point where you have to be on your computer exactly when they are released.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1359891578173669378-685" src="https://platform.twitter.com/embed/Tweet.html?id=1359891578173669378"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1359891578173669378-685');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1359891578173669378&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I decided it was time to combine my coding skills and knack for extreme efficiency (or laziness) to create a bot that would automate signing up for me. My original idea was to have a graphical user interface (GUI) on which I could enter my username and password, and then select the gym location, date, and time for the slot. After submitting the information, there would be a task scheduled 6 hours in advance of the gym time that would reserve a slot for me.&lt;/p&gt;

&lt;p&gt;After some research and deliberation, I decided on using the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Command line interface&lt;/strong&gt; (CLI): reserving a gym slot is as easy as opening the command prompt and entering my username and password along with the specific slot I want.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Selenium&lt;/strong&gt;: this is a Python library that wraps the Selenium Web Driver which can automate web tasks like clicking items and filling out forms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows Task Scheduler&lt;/strong&gt;: in order to schedule the scripts that reserve a gym slot, I used the Windows Task Scheduler on my computer. Later on, I will cover an option for those with different OSes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a video of it in action:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/TJp_b-Cvr_A"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You can view my code  &lt;a href="https://github.com/tmonty12/Gym-Sign-Up-Bot/blob/main/main.py" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Will You Learn?
&lt;/h2&gt;

&lt;p&gt;In this tutorial I will be walking you through how I created my gym web bot, but the topics can be transferable to scheduling and automating web tasks with the use of Selenium in Python. I will be teaching you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Basics of Selenium&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;navigating web pages&lt;/li&gt;
&lt;li&gt;selecting certain elements&lt;/li&gt;
&lt;li&gt;filling out forms&lt;/li&gt;
&lt;li&gt;waiting for elements to load&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implementing schedulers&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Windows Task Scheduler&lt;/li&gt;
&lt;li&gt;API for automating Windows Task Scheduler&lt;/li&gt;
&lt;li&gt;passing arguments to scripts&lt;/li&gt;
&lt;li&gt;alternative for Windows Task Scheduler&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;p&gt;In order to get started with this tutorial, I trust that you have  &lt;a href="https://www.python.org/downloads/" rel="noopener noreferrer"&gt;python downloaded&lt;/a&gt;  and a  &lt;a href="https://realpython.com/python-ides-code-editors-guide/" rel="noopener noreferrer"&gt;coding editor&lt;/a&gt;  (I use VSCode) that you prefer.&lt;/p&gt;

&lt;p&gt;I would also recommend  &lt;a href="https://towardsdatascience.com/getting-started-with-python-environments-using-conda-32e9f2779307" rel="noopener noreferrer"&gt;using an environment&lt;/a&gt;  (optional) to avoid cluttering your local environment and having issues with dependencies. After you have handled the tasks above, you can switch to your project environment (if you created one) and enter the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;selenium&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your next order of business is to download a Web Driver. This is what Selenium uses to access a browser and perform the tasks that you program it to do. I personally prefer Chrome so that is the browser I will be using for this tutorial. You can download the Chrome Web Driver  &lt;a href="https://sites.google.com/a/chromium.org/chromedriver/downloads" rel="noopener noreferrer"&gt;here&lt;/a&gt; . Make sure to save the path of the driver (the location of it in your file system) - we will need this later.&lt;/p&gt;

&lt;p&gt;You are now ready to automate web tasks!&lt;/p&gt;

&lt;h3&gt;
  
  
  Basics of Selenium
&lt;/h3&gt;

&lt;p&gt;Once you have a .py file opened and are ready to code, you first need to import webdriver from Selenium and instantiate the Chrome webdriver instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;

&lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webdriver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Chrome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;insert_webdriver_path_here&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we stored the webdriver instance in a variable, we will be able to use its various methods to interact with the web. Our first order of business is to go to a webpage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;driver&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="n"&gt;insert_target_url_here&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To start, I would choose a simple web page like Instagram. For my project, I have a function that determines the url based on the gym location selection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navigating a Web Page
&lt;/h3&gt;

&lt;p&gt;Now that we have landed on a web page, we need to be able to navigate to other pages and perform tasks. When arriving on my University’s gym website, I must first login. To do so, I click the login link in the top right corner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620237264416%2FK3yFngVnS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620237264416%2FK3yFngVnS.png" alt="Gym website home page login link"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are unfamiliar with html, it implements a Document Object Model (DOM) which is a hierarchical structure of elements that have certain attributes. For instance, links are stored in anchor elements with an href attribute which provides the url. Selenium has direct access to the DOM and can access specific elements like a link and perform actions on them like clicking. &lt;/p&gt;

&lt;p&gt;Selenium provides a couple of methods for selecting elements listed  &lt;a href="https://selenium-python.readthedocs.io/navigating.html" rel="noopener noreferrer"&gt;here&lt;/a&gt; . In order to locate elements that you want to interact with you can inspect the webpage with Google Chrome Dev Tools and use the element inspector.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620237344506%2FZ3sArsows.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620237344506%2FZ3sArsows.png" alt="Dev Tool inspecting login link"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The element inspector is circled in red and the element in the Dev Tools highlighted in blue refers to the login link. The login link has id “loginLink” so I did the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;login_link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;loginLink&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;login_link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Waiting For Elements To Load
&lt;/h3&gt;

&lt;p&gt;Because clicking on the login link redirects the browser to another page, it takes some amount of time for the web page to load along with its elements. If we tried to access an element on the login page right after clicking the login link, we’d experience an error because the page hasn’t loaded yet. Therefore, we need to implement Selenium’s explicit wait function.&lt;/p&gt;

&lt;p&gt;Selenium’s  &lt;a href="https://selenium-python.readthedocs.io/waits.html" rel="noopener noreferrer"&gt;WebDriverWait&lt;/a&gt;  waits for a certain condition to be true before it proceeds to access an element. To wait for the login page to load and access the username form field I wrote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium.webdriver.common.by&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;By&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium.webdriver.support.ui&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;WebDriverWait&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;selenium.webdriver.support&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;expected_condition&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;EC&lt;/span&gt;

&lt;span class="n"&gt;username_field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WebDriverWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;EC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;element_to_be_clickable&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;By&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we pass WebDriverWait the webdriver and the maximum amount of time (in seconds) we want the webdriver to wait. Then using the &lt;strong&gt;expected_condition&lt;/strong&gt; we can select the condition we are waiting for and pass it the element we want to select. Once the condition evaluates to true, the WebDriverWait function will return the selected element.&lt;/p&gt;

&lt;h3&gt;
  
  
  Filling out Forms
&lt;/h3&gt;

&lt;p&gt;Now that we have selected the username form field, we need to have the Web Driver input our username. To write in an element, we take the variable containing the element and use the send_keys() method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;insert_username_here&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can access the password field and insert your password with the instructions above. After submitting the login form, I am then redirected back to the web page for registering for a gym slot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessing those Hard to Select Element
&lt;/h3&gt;

&lt;p&gt;Now that I am back to the gym slot reservation page, I have encountered an issue. On the reservation page, there are multiple time slot cards of which I need to click the register button corresponding to the inputted gym time. However, each time slot card has the same attributes so I can’t access the correct time slot with name or id.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620237579548%2FDtt3OWTQc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620237579548%2FDtt3OWTQc.png" alt="Web page with multiple time slots"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where using Xpath comes in handy. Xpath stands for XML Path Language and allows you to navigate to certain elements of an XML document with a given path. When using the Google Chrome Dev Tools, you can right click on an element and copy its Xpath. Xpath also allows you to select an element based on the physical text it displays. Therefore, I am able to find the time slot card with the correct time and then navigate to the register button so that I can click it. &lt;/p&gt;

&lt;p&gt;To do so I write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;register_btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element_by_xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="o"&gt;//*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="n"&gt;mainContent&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;small&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;insert_text_to_match_here&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To visualize how I am navigating the DOM tree:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620237624111%2Fa5DvQm4yG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1620237624111%2Fa5DvQm4yG.png" alt="Register button dom tree navigation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After finding the card with the text that matches that correct gym time, I navigate up the DOM tree back to the card and then traverse down to the register button.&lt;/p&gt;

&lt;p&gt;With the above information, you should be able to navigate throughout a website, select elements - even in the most difficult situations, click on them, fill in forms and wait for elements to appear so that you can interact with them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing Schedulers
&lt;/h3&gt;

&lt;p&gt;A task scheduler allows for you to register scripts to be run given a certain time or condition. In the case of my gym reservation bot, I want it to reserve a gym slot 6 hours in advance of the time slot I selected.&lt;/p&gt;

&lt;p&gt;For this, I used the Windows Task Scheduler. It is a Windows Application with a GUI so you can open it, view default scheduled tasks and create your own task. When creating a task, you provide the scheduler a trigger - certain time of day or condition, an action - something to be executed in the command prompt, and conditions - when you want the task to run. &lt;/p&gt;

&lt;p&gt;Obviously I don’t want to have to open the app every time to schedule a task, so I need an application programming interface (API) that will allow me to write code to automatically schedule one. &lt;/p&gt;

&lt;h3&gt;
  
  
  Win32com Library
&lt;/h3&gt;

&lt;p&gt;The win32com is the API library that I choose to automate scheduling tasks on Windows. It is essentially a very thin Python wrapper that allows you to automate Windows Applications which in this instance is the Task Scheduler. To download the library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;pywin32&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the library is downloaded, you will be able to write code to interact with Task Scheduler. This  &lt;a href="https://medium.com/@ajay.bile007/programmatic-way-of-creating-task-in-windows-task-scheduler-8673c5d5b897" rel="noopener noreferrer"&gt;post&lt;/a&gt;  shows you exactly the code you need to write to schedule tasks but I’ll show you some small changes to make for my implementation&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start time&lt;/strong&gt;: set the start time of the task. For me, its 6 hours before the gym slot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repetitions&lt;/strong&gt;: set how many times you want the task to repeat. Since, I want the gym sign up task to only occur once (my schedule varies), I deleted the code for this altogether.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Path&lt;/strong&gt;: set action.Path to the path of your python interpreter. This will allows you to run python scripts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arguments&lt;/strong&gt;: set action.Arguments to the path of the script you want to execute and input any arguments for the script.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure additional conditions&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;DisallowStartIfOnBatteries = False → Will allow task to execute when your computer isn’t charging&lt;/li&gt;
&lt;li&gt;WakeToRun = True → Will wake up your computer when asleep to run a task.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Arg Parser
&lt;/h3&gt;

&lt;p&gt;In order to have my program operate as a CLI, I need to have a way to pass inputs such as the password, username, gym location, etc. to my script. To do this, I used the built-in Python library argparse. Argparse will allow you to define arguments for a python file, and extrapolate them into variables to be used in your program. &lt;/p&gt;

&lt;p&gt;For instance, to add an argument for time I wrote the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="n"&gt;Gym&lt;/span&gt; &lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="n"&gt;starting&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I define an argument -t that takes an input of type String and provide a help message that reminds me how to format the time.&lt;/p&gt;

&lt;p&gt;When running a python script from the command prompt, to pass the time argument, I write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then to extrapolate the argument variables I do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_args&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to access a specific argument you refer to the name of the argument. For instance, accessing the time argument I passed into the script earlier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same can be done for the rest of the variables you need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scheduler Alternatives
&lt;/h3&gt;

&lt;p&gt;If you have a Linux or Mac OS then you can use cron. Cron is the same as Windows Task Scheduler in that you can schedule tasks to run at a given time. This  &lt;a href="https://medium.com/macoclock/automate-running-a-script-using-crontab-on-macos-88a378e0aeac" rel="noopener noreferrer"&gt;post&lt;/a&gt;  goes into detail about how you can schedule python scripts. However, instead of using an API to schedule tasks, you use the command line. In code, you can use &lt;strong&gt;os.system()&lt;/strong&gt; in a python script in order to have commands executed at the command line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Putting it All Together
&lt;/h3&gt;

&lt;p&gt;For my gym bot project, I created two .py files, one for scheduling a task and one for executing the task. The scheduler.py file allows me to pass the information necessary to reserve a gym slot. For instance, say I wanted to reserve a spot at Ernie Gym at 4:00pm on May 5th as I do in the video example. I would type in the command prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="n"&gt;tjmontfo&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;pw&lt;/span&gt; &lt;span class="o"&gt;********&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2021&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;flr&lt;/span&gt; &lt;span class="n"&gt;ernie&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scheduler.py file will use this information to create a scheduled task at 10:00am on May 5th. When the task is executed, it will run the main.py file which will be passed the username, password, location and time and using the Selenium WebDriver, reserve a gym slot.&lt;/p&gt;

&lt;p&gt;This tutorial does not need to be specifically used for creating a gym reservation bot. Selenium in Python has extensive applications like scraping websites for data or testing applications. Also, it is not necessary to use Selenium in tandem with a scheduler like Windows Task Scheduler. Scheduling tasks just allows for scripts to be run in the background without having to remember to run them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Thank you for reading through the tutorial, I really hope you gained something from this. In fact, I challenge you to create something using Selenium in Python. It can be as simple as a web bot that logins into your Instagram account and likes a post. Please DM me a video of it in action or a Github repository of your code to my  &lt;a href="https://twitter.com/tmonty_12" rel="noopener noreferrer"&gt;twitter account&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;If you enjoyed my in-depth explanation of programming in Python please check out some of my other posts. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href="https://tmonty.tech/the-mystery-of-recursion-understanding-how-to-implement-it-in-python" rel="noopener noreferrer"&gt;The Mystery of Recursion - Understanding How to Implement it in Python&lt;/a&gt; &lt;/li&gt;
&lt;li&gt; &lt;a href="https://tmonty.tech/how-python-lists-work-under-the-hood" rel="noopener noreferrer"&gt;How Python Lists Work Under the Hood with a Baseball Example&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>tutorial</category>
      <category>productivity</category>
      <category>selenium</category>
    </item>
    <item>
      <title>Why Your Impression of a Hackathon is Wrong - You Are Missing Out</title>
      <dc:creator>Thomas Montfort</dc:creator>
      <pubDate>Mon, 29 Mar 2021 19:59:06 +0000</pubDate>
      <link>https://forem.com/tmontytech/the-ultimate-hackathon-guide-addressing-the-misconceptions-379</link>
      <guid>https://forem.com/tmontytech/the-ultimate-hackathon-guide-addressing-the-misconceptions-379</guid>
      <description>&lt;h3&gt;
  
  
  Addressing the Misconceptions
&lt;/h3&gt;

&lt;p&gt;If you don’t actually know what a hackathon is you are probably imagining the scene from &lt;em&gt;Social Network&lt;/em&gt; where Facebook hirees are challenged to a race to hack into a server. The scene takes place in a tightly packed room with a cheering audience and shots being forced down their throats.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x4yCER_---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1616872104110/cupYy7RvZ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x4yCER_---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1616872104110/cupYy7RvZ.gif" alt="hackathon scene from Social Network" width="363" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While I am unsure if this Facebook story is true, I can assure you that hackathons are nothing like this. The atmosphere is not of the high stake and competitive nature that &lt;em&gt;Social Network&lt;/em&gt; portrays but rather an &lt;strong&gt;innovative&lt;/strong&gt;, &lt;strong&gt;collaborative&lt;/strong&gt; and &lt;strong&gt;fun&lt;/strong&gt; environment.&lt;/p&gt;

&lt;p&gt;People hear the word “hackathon” and assume that some nefarious criminal activity is occurring. The “hack” part is not referring to the literal definition. It’s supposed to be a play on words &lt;em&gt;hack&lt;/em&gt; and &lt;em&gt;marathon&lt;/em&gt;. In fact, one of the intentions of hackathons is to create projects in 24-48 hours that solve real world problems. Hackathons encourage projects of this nature with certain prize categories like Best Climate Hack.&lt;/p&gt;

&lt;h4&gt;
  
  
  Some Definitions:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hackathon:&lt;/strong&gt; the event.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hacker:&lt;/strong&gt; a person who attends a hackathon.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hack:&lt;/strong&gt; the project a group or individual creates at a hackathon.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lastly, people have this belief that hackathons have very high barriers for entry because you must be a talented coder. First of all, writing code is only a small part of the many elements that go into a successful project. We need entrepreneurs to provide creative ideas, designers to help with logo design and UI, and business people to help pitch the final presentation to the judges. &lt;/p&gt;

&lt;p&gt;Also, if you do code but don't have much knowledge or want to learn, attending hackathons are a great way to gain resources and direction to learn. &lt;/p&gt;

&lt;p&gt;Most people have a very false image of what hackathons are, but by learning about what they actually are and the benefits they provide, you will not want to pass up on them. &lt;/p&gt;

&lt;h3&gt;
  
  
  So what is a hackathon then?
&lt;/h3&gt;

&lt;p&gt;Glad you asked. A hackathon is an &lt;strong&gt;invention marathon&lt;/strong&gt; where people from around the country and possibly the globe gather in one area for a weekend. Once assembled, they form teams, share ideas and collaborate to create an original project that addresses a problem. Throughout the hacking, there are many breaks for caffeine, free food, fun games, workshops and networking with reputable companies.&lt;/p&gt;

&lt;h4&gt;
  
  
  CuseHacks 2020:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d6E7EQYv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1616872963214/nc4eYkJIO.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d6E7EQYv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1616872963214/nc4eYkJIO.jpeg" alt="CuseHacks 2020" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You usually arrive at the hackathon on a Saturday where you check-in, meet your team or participate in team-building events to find teammates, and begin working on your project. When the hackathon is coming to a wrap on Sunday, you and your teammates demo your project to judges where you can win prizes for specific categories.&lt;/p&gt;

&lt;p&gt;The real magic of a hackathon is the actual projects that can be built in 24 hours. One famous example is  &lt;a href="https://techcrunch.com/2010/08/26/inception-a-hackday-dream-the-story-of-groupme/"&gt;GroupMe&lt;/a&gt;, where the founders locked themselves in a room during a 2010 hackathon in NYC to code out their communication app idea. The amazing thing is they didn’t even win any prizes but felt so confident about their idea that they quit their full-time jobs to pursue it. This risk paid off a year later when Skype purchased GroupMe for $85 million.&lt;/p&gt;

&lt;p&gt;The power of a community of innovators and technical people coming together for a weekend of sharing ideas and knowledge and addressing problems, creates an incredible atmosphere. Hackers are able to consult mentors, professionals in the industry or peers for advice. The abundance of resources allows for lasting connections and great learning opportunities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alright, so why should I attend a hackathon?
&lt;/h3&gt;

&lt;p&gt;After learning about what a hackathon actually is you should be convinced but let me just give some more motivation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learn industry skills:&lt;/strong&gt; By attending an event with a community of tech innovators, you will be sure to learn about new emerging technologies that you can incorporate in your own work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Networking:&lt;/strong&gt; Hackathons are great for networking because they allow you to talk to employees at top-tier companies like IBM who are passionate and have experience in your field of work unlike recruiters. It also can lead to great first impressions because you can directly showcase your skills through your project.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  IBM Table at CuseHacks 2020:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NQoZ0bBz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1616873046397/xi7KimqfV.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NQoZ0bBz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1616873046397/xi7KimqfV.jpeg" alt="IBM Table at CuseHacks 2020" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Great community:&lt;/strong&gt; When attending a hackathon, you can easily meet like-minded individuals. It's a great place to discuss ideas and make great connections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resume builder:&lt;/strong&gt; Hackathons are very attractive on your resume because they display your passion for the industry and provide the opportunity to build a project that you can put on it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free stuff:&lt;/strong&gt; With the reasons mentioned above, you might be skeptic that a hackathon is free. However, not only is attending free, but so is the food, drinks and swag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;They’re fun:&lt;/strong&gt; It’s basically like having a sleepover with friends where you have the latitude to create whatever you want and spend your time however you choose whether that be actually creating a project or attending workshops and games.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I understand that even with the above reasons, that you may still be hesitant about attending a hackathon. If you have never attended one before and have no friends to accompany you, it might seem daunting to attend. However, I can assert to you that the hackathon community is very welcoming. It’s also not even required to build a project so you can attend only to make friends, learn and abuse the free stuff. &lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;p&gt;Now that you have decided you want to attend a Hackathon, you are probably now thinking about where you can find them. Well there are two awesome resources that can lead you in the right direction.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;a href="https://mlh.io"&gt;Major League Hacking&lt;/a&gt;  (MLH):
&lt;/h4&gt;

&lt;p&gt;MLH is the official student hackathon league. They help support 200 weekend long hackathons every year. You are able to find upcoming hackathons through their event page. They also provide other resources for hackers including internship and fellowship opportunities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Qa2XHf2V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1616873182179/2G6dQGdgA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Qa2XHf2V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1616873182179/2G6dQGdgA.png" alt="Major League Hacking Logo" width="346" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;a href="https://devpost.com"&gt;Devpost&lt;/a&gt; :
&lt;/h4&gt;

&lt;p&gt;Devpost is basically like the social media for hackathons. You have the ability to create an account which you will use to submit your projects for hackathons. Your profile will be populated with all of the projects you submitted including any prizes that you won for specific categories.&lt;/p&gt;

&lt;p&gt;Devpost is also a great place to find hackathons as they include more than just the MLH sponsored events and have a great search filter system for location, length and interest&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Personally, I held some of the same misconceptions I addressed. However, I joined the Innovate Orange club this winter at Syracuse University that hosts &lt;a href="https://innovateorange.github.io/cusehacks/"&gt;CuseHacks&lt;/a&gt; . When helping moderate the event this year, I was able to connect with experienced industry professionals and learn about newer technologies like  &lt;a href="https://venturebeat.com/2019/12/26/gan-generative-adversarial-network-explainer-ai-machine-learning/"&gt;GANs&lt;/a&gt; . I only moderated, but it was still fun and beneficial to me!&lt;/p&gt;

&lt;h4&gt;
  
  
  My teammates and I at CuseHacks 2021:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3gI8_6EW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1616873210427/Cxxw6RCNp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3gI8_6EW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1616873210427/Cxxw6RCNp.png" alt="CuseHacks 2021" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think the biggest thing holding back hackathons is the misconception that you need to know how to code. However, we actually need people with different specializations from backgrounds like design, business and entrepreneurship. Trust me, coders often lack the creativity for ideas or the business skills to pitch their project, so those who have these specializations would make a huge impact.&lt;/p&gt;

&lt;p&gt;If you have never attended a hackathon before, the best advice is to go in open-minded. While some experienced hackathoners will go in with a project idea and only focus on winning a prize, don’t let those select few scare you. The real reason to attend a hackathon is to meet like minded people and learn. &lt;/p&gt;

&lt;p&gt;If you have made it this far, please consider attending a hackathon. They are not just for students. While a lot of hackathons are hosted by Universities, there are also companies like Amazon who will host hackathons for those who are in industry. They also come in different forms like remote or extended periods of time instead of the traditional in-person weekend events.&lt;/p&gt;

&lt;p&gt;Feel free to reach out to me on  &lt;a href="https://twitter.com/tmonty_12"&gt;twitter&lt;/a&gt; if you have any questions. &lt;/p&gt;

</description>
      <category>hackathon</category>
      <category>mlh</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The Mystery of Recursion - Understanding How to Implement it in Python</title>
      <dc:creator>Thomas Montfort</dc:creator>
      <pubDate>Fri, 05 Feb 2021 16:34:54 +0000</pubDate>
      <link>https://forem.com/tmontytech/the-mystery-of-recursion-understanding-how-to-implement-it-in-python-4d34</link>
      <guid>https://forem.com/tmontytech/the-mystery-of-recursion-understanding-how-to-implement-it-in-python-4d34</guid>
      <description>&lt;h2&gt;
  
  
  What is Recursion?
&lt;/h2&gt;

&lt;p&gt;If you understand the underlying concept of recursion but struggle to implement it like myself, or you don't even know what it is, then this post if for you.&lt;/p&gt;

&lt;p&gt;Recursion is defined as solving a complex problem by breaking the problem into smaller versions of itself that can be solved. In programming, this is done by having a function call itself.&lt;/p&gt;

&lt;p&gt;The underlying principle of recursion are these two cases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Base Case&lt;/strong&gt;: this case defines the smallest instance of a problem. In certain recursive solutions, there can be multiple base cases but for the purpose of this post's explanation, my example will only incorporate one. When coding, the base case prevents an infinite loop of the function calling itself.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Recursive Case&lt;/strong&gt;: this case manipulates the problem in order to approach the base case. In programming, this is the case in which the function calls itself.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Put simply, the recursive case will breakdown the problem until it arrives at the base case, after which the the sub solutions build up to solve the original problem.&lt;/p&gt;

&lt;p&gt;Do not worry if your understanding of recursion is hazy because the above definitions will make sense when implementing a recursive solution in Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Call Stack
&lt;/h2&gt;

&lt;p&gt;In order to truly understand how recursion is implemented in Python, it is necessary to familiarize yourself with the call stack. &lt;/p&gt;

&lt;p&gt;The call stack uses the stack data structure to keep track of local variables and previous function calls. The stack is a last-in, first-out data structure. This means that the last item to be placed in the stack will be the first to be removed. To help visualize, think of a stack of plates:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9wmd8X_V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612217672194/K8ZCDamI8.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9wmd8X_V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612217672194/K8ZCDamI8.jpeg" alt="brooke-lark-sG-PR0BNwb4-unsplash.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whatever plate is placed last on the stack is the first one to be removed.&lt;/p&gt;

&lt;p&gt;In terms of programming, the stack has two simple operations: push and pop. Push adds an item onto the stack and pop removes an item from the stack, returning its value.&lt;/p&gt;

&lt;p&gt;In python, the call stack consists of frames. The bottom most frame is the global or module frame. This consists of all the global variables. Every time a function is called a new frame is pushed onto the stack containing its local variables and function arguments. When a function call returns, the frame is popped off the stack and its value is passed to where it was called in the previous frame.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Famous Recursion Example - Factorial
&lt;/h2&gt;

&lt;p&gt;The factorial of a number is defined as so:&lt;/p&gt;

&lt;p&gt;4! = 4 * 3 * 2 * 1 = 24&lt;/p&gt;

&lt;p&gt;If we were to define the factorial of a number &lt;strong&gt;n&lt;/strong&gt; as a mathematical equation, it would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The right side of the equation will be the &lt;em&gt;recursive case&lt;/em&gt; of our solution. Notice, how the recursive case takes the original problem, &lt;strong&gt;factorial(n)&lt;/strong&gt;, and makes it a simpler problem of multiplying &lt;strong&gt;n&lt;/strong&gt; by whatever &lt;strong&gt;factorial(n-1)&lt;/strong&gt; is.&lt;/p&gt;

&lt;p&gt;We can define a function &lt;strong&gt;factorial&lt;/strong&gt; that takes a parameter &lt;strong&gt;n&lt;/strong&gt;. However, if we only defined this function with the above equation, it would call itself infinitely leading to an error.&lt;/p&gt;

&lt;p&gt;This is because we did not define a &lt;em&gt;base case&lt;/em&gt;. The most basic factorial is the factorial of 1 which equals 1. So we can tell the program that once it reaches the factorial of 1, instead of calling &lt;strong&gt;1 * factorial(0)&lt;/strong&gt;, to just &lt;strong&gt;return 1&lt;/strong&gt;. After which, the Python call stack will handle multiplying out the numbers.&lt;/p&gt;

&lt;p&gt;After defining both the recursive and base cases, we arrive at the Python program below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  In Depth Recursive Function Implementation
&lt;/h2&gt;

&lt;p&gt;Before calling the factorial function, the Python call stack would look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zbV7Jxa6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612222009642/RKv1SGozi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zbV7Jxa6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612222009642/RKv1SGozi.png" alt="Call Stack - 1 (3).png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, we call the factorial function passing in an argument of 4.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A frame for the factorial function would be pushed onto to the call stack, setting the argument &lt;strong&gt;n&lt;/strong&gt; equal to &lt;strong&gt;4&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---mEDbgwr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612222128046/cNmno7-YI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---mEDbgwr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612222128046/cNmno7-YI.png" alt="Call Stack - 2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Python interpreter will then process the function and since &lt;strong&gt;n&lt;/strong&gt; is not &lt;strong&gt;&amp;lt;= 1&lt;/strong&gt;, it will evaluate &lt;strong&gt;n * factorial(n-1)&lt;/strong&gt;. However before the function can return a value, it must evaluate &lt;strong&gt;factorial(n-1)&lt;/strong&gt;. This will cause another factorial frame to be pushed on the stack, with the argument &lt;strong&gt;n&lt;/strong&gt; set to &lt;strong&gt;3&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sycJlJiM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612222294743/zXgfi23TF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sycJlJiM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612222294743/zXgfi23TF.png" alt="Call Stack - 3.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, since &lt;strong&gt;n&lt;/strong&gt; is not &lt;strong&gt;&amp;lt;= 1&lt;/strong&gt;, the function will evaluate &lt;strong&gt;n * factorial(n-1)&lt;/strong&gt;. Likewise, the function must evaluate &lt;strong&gt;factorial(n-1)&lt;/strong&gt; before returning a value. &lt;/p&gt;

&lt;p&gt;This pattern will continue until the factorial frame with the argument n equal to 1 is pushed onto the stack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0UrQ9dFb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612222730246/6jJduzt8q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0UrQ9dFb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612222730246/6jJduzt8q.png" alt="Call Stack - 5 (1).png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When this occurs, the function reaches the base case, so it instead returns 1. As I mentioned early when explaining the call stack, when a function returns, it pops its frame off the stack, transferring its value to where it was called in the previous frame.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KR8CZOIK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612222867866/Npx8dueYc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KR8CZOIK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612222867866/Npx8dueYc.png" alt="Call Stack - 6.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now since the value for &lt;strong&gt;factorial(n-1)&lt;/strong&gt; has been evaluated, the factorial function can evaluate the product and return it to the previous frame, pushing the current frame off the stack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BVJ9KS9l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612222963799/kJ7D_a-7I.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BVJ9KS9l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612222963799/kJ7D_a-7I.png" alt="Call Stack - 7.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This pattern continues until we reach the original function call...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jihVhTbE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612223032269/rxZsqVaa8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jihVhTbE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1612223032269/rxZsqVaa8.png" alt="Call Stack - 8.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you might have guessed, the factorial function with argument 4 returns a value of 24.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;When writing a recursive solution in Python, think of the problem in terms of a base case and recursive case. Ask yourself: "How can I define a recursive case that will help me reduce the problem towards a base case?"&lt;/p&gt;

&lt;p&gt;When trying to understand a recursive solution, I find it best to visualize the call stack in my head.  Every time a function is called an item is added onto the stack and any time you encounter the return keyword, it pops an item off the stack and returns its value to the previous function call.&lt;/p&gt;

&lt;p&gt;If you have made it this far and have enjoyed my post, please follow me on  &lt;a href="https://hashnode.com/@tmonty"&gt;Hashnode&lt;/a&gt;  and  &lt;a href="https://twitter.com/tmonty_12"&gt;Twitter&lt;/a&gt;. I plan on posting more content and am open to suggestions or requests!&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
