Robert Johns | 18 Feb, 2025
Fact checked by Jim Markus

40+ Python Projects + Source Code | Beginner to Portfolio

The best way to learn Python? Build real projects.

When you code hands-on, you retain more, stay motivated, and develop skills that actually matter. No more passively memorizing syntax—you’ll be applying what you learn right away.

The only problem? Finding the right project ideas.

That’s where I come in. I've created more than 40 real-world, portfolio-worthy Python projects—ranging from beginner-friendly builds to professional-level applications, all with step-by-step tutorials, and even video walkthroughs. Whether you're just starting or sharpening your skills, these projects will help you level up.

Let’s start coding!

Professional Portfolio Projects

I've designed each of these projects to act like step-by-step tutorials, so it's almost like taking a free Python course while growing your Python portfolio.

Web Scraping for Python Automated Real Estate Data Pipeline with Dashboard

A Python-based web scraping project using Selenium to extract real estate listings, including prices, addresses, bedrooms, bathrooms, and geolocation data, forming the foundation of an automated data pipeline.This is Part 1 of a four-part series on building a Python Automated Real Estate Data Pipeline. In this stage, we focus on web scraping real estate listings using Selenium to extract key property details like prices, addresses, beds, baths, and geolocation data. The collected data is stored in a structured format, setting the foundation for analysis in the next phase.

Want to master web scraping and build a real-world data pipeline that's worthy of a professional portfolio? This web scraping project is the perfect challenge.

Data Analysis for Python Automated Real Estate Data Pipeline with Dashboard

A Python data analysis project focused on cleaning and processing real estate data using Pandas and NumPy to handle missing values, format numerical data, and explore property trends.This is Part 2 of a four-part series on building a Python Automated Real Estate Data Pipeline. In this stage, we focus on cleaning and analyzing the scraped real estate data to prepare it for visualization and deeper insights.

Using Pandas, NumPy, Matplotlib, and Seaborn, we handle missing values, format numerical data, and explore trends in property prices, sizes, and features. This step ensures our dataset is structured, reliable, and ready for interactive visualization in Part 3.

Want to sharpen your data analysis skills while working on a real-world data pipeline? This data analysis project is the perfect hands-on experience!

Streamlit Dashboard for an Automated Real Estate Data Pipeline

A Python-based interactive real estate dashboard built with Streamlit, Folium, Matplotlib, and Seaborn, allowing users to filter listings, view price distributions, and explore trends through interactive maps and graphsThis is Part 3 of a four-part series on building a Python Automated Real Estate Data Pipeline. In this stage, we focus on building an interactive dashboard using Streamlit to visualize real estate trends dynamically.

With Streamlit, Folium, Matplotlib, and Seaborn, we create a user-friendly interface where users can filter listings by price, bedrooms, bathrooms, and square footage, explore interactive maps, and analyze price distributions and market trends in real time.

Want to build a fully interactive, data-driven application that turns raw real estate data into valuable insights? This dashboard project is the perfect opportunity to showcase your skills!

Automating and Tracking Historical Data for Python Real Estate Data Pipeline

A Python project automating real estate data collection with APScheduler, storing timestamped datasets, tracking price trends over time, and integrating historical insights into a Streamlit dashboard.This is Part 4 and the final installment of a four-part series on building a Python Automated Real Estate Data Pipeline. In this stage, we take our project to the next level by implementing automation and historical tracking, allowing our scraper to run on a schedule and accumulate data over time.

With APScheduler, we automate the scraping and analysis processes, ensuring real-time data collection. We also enhance our pipeline by storing timestamped datasets, tracking price trends, and integrating historical filtering into our Streamlit dashboard for deeper real estate insights.

Want to build a fully automated, real-world data pipeline that continuously tracks market trends? This final automation and historical tracking project is the perfect way to complete your portfolio-worthy project!

Python File Organizer App

A Python-based file organizer application that automatically sorts and categorizes files into folders based on type.Tired of a cluttered downloads folder? A Python file organizer is a perfect project to simplify your life while leveling up your coding skills. Using Python’s os and shutil modules, you’ll learn to automate file sorting into categories like Images, Videos, and Documents. It’s beginner-friendly, practical, and introduces you to file handling, directory management, and automation.

Want to streamline your workflow and learn Python automation? Try your hand at building this Python file organizer app with me as I've created a video walkthrough to guide you every step of the way.

Python Unit Converter App with GUI

A Python unit converter application with a graphical user interface built using Tkinter, featuring input fields, dropdown menus for unit selection, and a conversion result displayA Python unit converter app is an excellent project to learn GUI programming with tkinter and practical Python skills. It lets you create a user-friendly tool to convert units like miles to kilometers or Fahrenheit to Celsius, while introducing key concepts like reusable functions, dynamic UI updates, and basic mathematical operations.

Want a hands-on way to sharpen your Python skills and build something you can use daily? Dive in and build your own Python unit converter app with me as I've created a video tutorial to guide you step by step.

Python QR Code Generator App with GUI

A Python-based QR code generator with a graphical user interface built using Tkinter, featuring an input field for text or URLs, a generate button, and a display area for the generated QR codeA Python QR code generator is a fun and practical project that enhances your skills in GUI development and image processing.

Using libraries like qrcode, tkinter, and Pillow, you’ll create a user-friendly app to generate QR codes for URLs, contact info, or secret messages with just a few clicks.

Want to combine creativity with coding and build something useful?

Try building this Python QR code app with me as I've created a video walkthrough to help you follow along step by step.

 

Python Image Editor App with GUI

A Python-based image editor with a graphical user interface built using Tkinter, featuring buttons for applying effects, saving images, and undoing changesA Python image editor is a practical and creative project that enhances your programming skills. By using Pillow for image processing and tkinter for GUI development, you’ll create an app that can load, edit, and save images with filters like blur, sharpen, and more.

Want to sharpen your Python skills while building a real-world tool? Test yourself by building this image editor app in Python with me as I've created a video tutorial to to guide you every step of the way.

Python PDF Merger App with GUI

A Python-based PDF merger application with a graphical user interface built using PyQt, featuring buttons to add and remove PDFs, merge files, and save the newly created PDFA Python PDF merger app is a practical project that combines the power of PyPDF2 for PDF manipulation and tkinter for GUI development. By using Object-Oriented Programming (OOP), you’ll create an intuitive app that allows users to select, manage, and merge multiple PDF files seamlessly.

Want to build a tool that's both useful and educational? Try your hand at building this PDF merger app with me and check out the video walkthrough I've made to guide you step by step.

Python URL Shortener App with GUI

A Python URL shortener application with a graphical user interface built using PyQt, allowing users to input a URL, generate a shortened link, and copy it to the clipboard with a single button click.A Python URL shortener is a fun and practical project that combines functionality with a polished GUI. Using PyQt5 for the interface and pyshorteners for URL generation, you’ll create a sleek application that shortens long URLs and copies them to the clipboard.

Want to enhance your Python skills while building a visually appealing and useful tool? Test your skills by building this URL shortener app.

Python Real-Time Error Notification App

A Python log monitoring system that automates real-time file monitoring and notifications using Watchdog for detecting file changes and smtplib for sending email alerts, helping developers and system admins track critical events or errors instantlyA Python log monitoring system is a practical project to automate real-time file monitoring and notifications. Using watchdog for file changes and smtplib for email alerts, you’ll create a tool that detects critical events or errors in logs and notifies you instantly.

Want to streamline your workflow and build a tool that’s useful for developers and system admins? This project is a perfect choice, so dive in and build this error notification app.

Fun & Interactive Games

Python Hangman Game with GUI

A Python-based Hangman game with a graphical user interface built using Tkinter, displaying a word guessing interface and a hanging figure.A Python Hangman Game combines fun and practicality, making it an excellent project for both learning and showcasing your coding skills. With Tkinter for the GUI and OOP for structure, you can create a game that’s both interactive and scalable.

Want to explore how Python can bring games to life while enhancing your programming skills? Jump in and start building this Python hangman project.

 

Tic-Tac-Toe Game with GUI

A Python Tic Tac Toe game with a modern graphical user interface created using PyQt, featuring an interactive grid for two-player gameplay.A Tic-Tac-Toe game is a great project to learn Object-Oriented Programming (OOP), GUI design, and event handling in Python using PyQt5. This beginner-friendly project will help you master interactive UI components, button handling, and game logic implementation in Python.

By the end of this step-by-step tutorial, you'll have a fully functional Tic-Tac-Toe game where two players can compete in a graphical interface, making it an excellent portfolio project! Want to test yourself, try your hand at this tic-tac-toe project.

 

Blackjack Game with GUI

A Python Blackjack card game built with PyQt and object-oriented programming, showcasing a digital card table with player and dealer handsA Blackjack game is an exciting project that combines game logic, OOP, UI development, and event handling in Python using PyQt5. This is perfect for anyone looking to improve their Object-Oriented Programming (OOP) skills while creating an interactive, real-world game.

By the end of this blackjack project tutorial, you'll have a fully functional Blackjack game where you can play against the dealer using an intuitive graphical interface. This is a great portfolio project to demonstrate Python programming and UI development expertise.

Pac-Man Game

A Python recreation of the classic Pac-Man arcade game using Pygame, featuring a maze, collectible dots, and moving ghosts.A Python Pac-Man game is a fun project to learn game development concepts with Pygame. This is perfect for beginners who want to learn 2D game mechanics, and collision detection.

By the end of this tutorial, you'll have a fully playable Pac-Man game where you can navigate a maze, eat pellets, and avoid ghosts—all while sharpening your Python programming skills.

Pong Arcade Game

A retro-style Pong game implemented in Python using the Turtle module, displaying two paddles and a bouncing ball.A Pong Arcade Game is a fun project that introduces you to essential game development concepts in Python using the built-in Turtle module. This is perfect for beginners who want to learn object movement, collision detection, and user input handling in a simple yet exciting environment.

By the end of this step-by-step tutorial, you'll have a fully playable Pong game where two players can compete by controlling paddles to bounce the ball back and forth — all while building your Python skills.

 

Speed Typing Test

A Python speed typing test application with a graphical interface built using Tkinter and object-oriented programming, featuring a text input field and word tracking.A speed typing test is a fun and challenging project that introduces essential GUI development in Python using Tkinter. This is perfect if you want to learn event handling, user input validation, and time-based calculations in an interactive environment.

By the end of this tutorial, you'll have a fully functional speed typing test where users can measure their typing speed and track their Words Per Minute (WPM).

Python Projects for Beginners

If you're new to the language or still learning Python, these are the perfect projects for you to dive into, as they're designed to help you grasp some fundamental concepts of Python programming. Plus if you're looking for some extra help, I've also released my own course, Python with Dr. Johns, where I take an academic approach to teaching while also building portfolio-worthy Python projects.

Mad Libs Generator 

A terminal-based Python Mad Libs Generator that takes user input to dynamically fill in story templates, creating fun and unexpected sentences using string manipulation and loops.A Python Mad Libs Generator is a fun and interactive way to practice user input, string manipulation, and loops. This beginner-friendly project allows users to enter words that are dynamically inserted into a story template, generating hilarious and unexpected results.

Looking for a creative and engaging way to sharpen your Python skills? This Mad Libs project is the perfect choice!

Number Guessing 

A terminal-based Python Number Guessing Game where players try to guess a randomly generated number, receiving hints and tracking their best score while learning about loops and user input handling.A Python Number Guessing Game is an exciting and beginner-friendly project that introduces random number generation, loops, and user input handling. This interactive game challenges players to guess a randomly chosen number, providing hints along the way while tracking their best score.

Looking for a fun way to practice core Python concepts while building a simple yet engaging game? This number guessing project is the perfect choice.

Rock Paper Scissors

A terminal-based Python Rock Paper Scissors game that lets users compete against the computer, utilizing randomization, loops, and conditionals to determine the winner in multiple roundsA Rock Paper Scissors game is a fun and interactive Python project that reinforces user input handling, randomization, and game logic. This beginner-friendly project allows players to compete against the computer, keeping track of scores and allowing multiple rounds.

Want to practice Python loops, conditionals, and user input validation while building a classic game? This rock-paper-scissors project is the perfect challenge.

Dice Roll Generator

A terminal-based Python Dice Roll Generator that simulates rolling one or two dice, using random number generation, user input validation, and loops for an interactive experience.A Dice Roll Generator is a simple yet engaging Python project that simulates rolling one or two dice. This project introduces random number generation, user input validation, loops, and screen clearing, making it perfect for beginners.

Want to learn how to create interactive Python programs while building a tool that can be used for board games, RPGs, or just for fun? This dice roll project is an excellent way to test yourself.

Calculator

A terminal-based Python Calculator that performs basic arithmetic operations, exponentiation, and includes a memory feature, showcasing modular function-based programming and user input handlingA Python Calculator is a simple yet powerful project that allows users to perform basic arithmetic operations, exponentiation, and store or recall results using a memory feature. This project introduces user input handling, function-based modular programming, loops, and conditional logic, making it a great choice for beginners.

Want to learn how to build interactive Python programs while developing a practical tool for quick calculations? This calculator project is an excellent way to sharpen your coding skills.

Password Strength Checker

A terminal-based Python Password Strength Checker that evaluates password security based on entropy, length, and character diversity, helping users create stronger passwords using cybersecurity best practices.A Python password strength checker is a practical project that evaluates password security based on entropy, length, and character diversity. This introduces secure password handling, entropy calculations, user input validation, and looping for multiple checks, making it an excellent choice for beginners interested in cybersecurity.

Want to learn how to analyze password strength and improve security best practices? This password checker project is a great way to enhance your Python skills while building a useful security tool.

Countdown Clock and Timer

This Python project idea is fun! Here, we’ve created a countdown timer that asks the user for a number of seconds via user input, and it then counts down, second by second, until it displays a message.

We’ve used the Python time module’s .sleep() function to pause for 1-second intervals. We combine this with some nifty string formatting to produce the countdown display.

Source Code:

'''
Countdown Timer
-------------------------------------------------------------
'''


import time


def countdown(user_time):
   while user_time >= 0:
       mins, secs = divmod(user_time, 60)
       timer = '{:02d}:{:02d}'.format(mins, secs)
       print(timer, end='\r')
       time.sleep(1)
       user_time -= 1
   print('Lift off!')


if __name__ == '__main__':
   user_time = int(input("Enter a time in seconds: "))
   countdown(user_time)

Number to Words

This Python project idea converts an integer number provided via user input to its equivalent words. This program is set up to support numbers with a maximum of 12 digits, but feel free to modify the program to handle larger numbers (hint: requires conditional statements and loops).

As an easy-to-understand example of basic Python projects, this simple but effective program can expand your skills with loops, user input, and conditional statements, not to mention Python tuples and lists.

You’ll also be able to experiment with some mathematical operations that may be new to you like the modulo (%) operator to return the remainder from integer division.

If any of these techniques are new to you, you might consider installing an AI coding assistant in your Python IDE to help offer help with any code blocks you find challenging to understand.

Source Code:

'''
Numbers To Words
-------------------------------------------------------------
'''


ones = (
   'Zero', 'One', 'Two', 'Three', 'Four',
   'Five', 'Six', 'Seven', 'Eight', 'Nine'
   )

twos = (
   'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen',
    'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen'
   )

tens = (
   'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty',
    'Seventy', 'Eighty', 'Ninety', 'Hundred'
   )

suffixes = (
   '', 'Thousand', 'Million', 'Billion'
   )

def fetch_words(number, index):
   if number == '0': return 'Zero'

   number = number.zfill(3)
   hundreds_digit = int(number[0])
   tens_digit = int(number[1])
   ones_digit = int(number[2])

   words = '' if number[0] == '0' else ones[hundreds_digit]
  
   if words != '':
       words += ' Hundred '

   if tens_digit > 1:
       words += tens[tens_digit - 2]
       words += ' '
       words += ones[ones_digit]
   elif(tens_digit == 1):
       words += twos[((tens_digit + ones_digit) % 10) - 1]
   elif(tens_digit == 0):
       words += ones[ones_digit]

   if(words.endswith('Zero')):
       words = words[:-len('Zero')]
   else:
       words += ' '

   if len(words) != 0:
       words += suffixes[index]
      
   return words


def convert_to_words(number):
   length = len(str(number))
   if length > 12:
       return 'This program supports a maximum of 12 digit numbers.'

   count = length // 3 if length % 3 == 0 else length // 3 + 1
   copy = count
   words = []

   for i in range(length - 1, -1, -3):
       words.append(fetch_words(
           str(number)[0 if i - 2 < 0 else i - 2 : i + 1], copy - count))
      
       count -= 1

   final_words = ''
   for s in reversed(words):
       final_words += (s + ' ')

   return final_words

if __name__ == '__main__':
   number = int(input('Enter any number: '))
   print('%d in words is: %s' %(number, convert_to_words(number)))

Fibonacci Generator

The Fibonacci numbers may be some of the most important numbers in our lives as they appear so often in nature.

The Python code below generates the Fibonacci numbers up to a certain length using recursion (yes, more recursion!). To stop the computation times from getting out of hand, we’ve implemented memoization to cache values as we calculate them.

You’ll notice that for this recursive algorithm, the base case is set to check whether the given Fibonacci sequence value is already stored in the cache. If so, it returns this (which is a constant time complexity operation), which saves a tremendous amount of computation time.

Source Code:

'''
Fibonacci Sequence
-------------------------------------------------------------
'''

fib_cache = {}


def fib_memo(input_val):
   if input_val in fib_cache:
       return fib_cache[input_val]

   if input_val == 0:
       val = 0
   elif input_val < 2:
       val = 1
   else:
       val = fib_memo(input_val - 1) + fib_memo(input_val - 2)

   fib_cache[input_val] = val
   return val


if __name__ == '__main__':
   print('======== Fibonacci Series ========')
   for i in range(1, 11):
       print(f'Fibonacci ({i}) : {fib_memo(i)}')

Bonus Project: Age Calculator

I recently made a new project based on a reader request. The novice programmer wanted to make an age calculator in Python, but he was having trouble. That's why I wrote this article.

Like my projects above, this one contains source code and an explanation about why I used the code I used.

Practical Tools & Utilities

Python Email Sender with Gmail and SMTP

A Python Gmail SMTP Email Sender is a practical automation project that allows you to send emails programmatically. Using Python’s smtplib module and Gmail’s SMTP service, you can automate notifications, reports, and alerts while securely managing credentials with dotenv.

Want to integrate email functionality into your Python projects? This project is a great way to learn how to set up Gmail SMTP, securely storing credentials, and creating a reusable email-sending function!

Password Generator

This is an interesting Python project that uses the secrets and string modules to generate a strong and secure password, much like you can with popular password managers.

The string module obtains all possible letters, digits, and special characters, while the secrets module allows us to obtain cryptographically secure passwords.

The code for this project is relatively simple as it uses a loop to continually generate passwords until it contains at least one special character and two digits. You can, of course, modify this to fit your own super-strong password rules!

Source Code:

'''
Password Generator
-------------------------------------------------------------
'''


import secrets
import string


def create_pw(pw_length=12):
   letters = string.ascii_letters
   digits = string.digits
   special_chars = string.punctuation

   alphabet = letters + digits + special_chars
   pwd = ''
   pw_strong = False

   while not pw_strong:
       pwd = ''
       for i in range(pw_length):
           pwd += ''.join(secrets.choice(alphabet))

       if (any(char in special_chars for char in pwd) and
               sum(char in digits for char in pwd) >= 2):
           pw_strong = True

   return pwd


if __name__ == '__main__':
   print(create_pw())

Currency Converter

This is one of several Python project ideas that require us to install one of the most popular Python libraries, which in this case, is the requests module. This is not included with the Python standard library, so use the pip command shown in the source code to install it on your system.

With the requests module, we can make HTTP requests to the Fixer API, allowing us to convert one currency to another. You’ll likely notice that we’re using a 3rd party API, so you’ll need to sign up to get a free API key. You can then enter your API key into the field shown in the source code, and you’ll be ready to go!

This project allows you to gain some more practice with loops and user input, but it expands on this with HTTP requests to retrieve API data in JSON format.

If you’re unfamiliar with JSON, it’s very similar to a Python dictionary, meaning we can access key-value pairs to fetch the data we’re after. In this case, we are looking for the currency conversion result from the API call.

Look at the docs on the Fixer API site for more details on the different data you can retrieve.

Source Code:

'''
Currency Converter
-------------------------------------------------------------
pip install requests
'''


import requests


def convert_currency():
   init_currency = input('Enter an initial currency: ')
   target_currency = input('Enter a target currency: ')

   while True:
       try:
           amount = float(input('Enter the amount: '))
       except:
           print('The amount must be a numeric value!')
           continue

       if not amount > 0:
           print('The amount must be greater than 0')
           continue
       else:
           break

   url = ('https://api.apilayer.com/fixer/convert?to='
          + target_currency + '&from=' + init_currency +
          '&amount=' + str(amount))

   payload = {}
   headers = {'apikey': 'YOUR API KEY'}
   response = requests.request('GET', url, headers=headers, data=payload)
   status_code = response.status_code

   if status_code != 200:
       print('Uh oh, there was a problem. Please try again later')
       quit()

   result = response.json()
   print('Conversion result: ' + str(result['result']))


if __name__ == '__main__':
   convert_currency()

Automatic Birthday Mail Sending

This Python project uses the standard smtplib, EmailMessage, and datetime modules, in addition to pandas and openpyxl (these need to be pip installed, as shown below) to send automated birthday emails.

This program reads from an Excel sheet that contains all of your friends’ details (see Excel sheet format in source code below). It then sends them an email if today is their big day before making a note in your spreadsheet to say they’ve received their email.

We’ve used the smtplib and EmailMessage modules to create an SSL connection to our email account and message. We’ve then used a pandas dataframe to store spreadsheet-style data within the Python program (an essential skill for data scientists). Finally, we used date formatting with the datetime module’s .strftime() function.

So, lots of new skills to get to grips with!

Important note: See my project on how to set up Gmail for Python before tackling this project.

Source Code:

'''
Birthday Email Sender
-------------------------------------------------------------
pip install pandas openpyxl
excel file cols:
Name, Email, Birthday (MM/DD/YYYY), Last Sent (YYYY)
'''


import pandas as pd
from datetime import datetime
import smtplib
from email.message import EmailMessage


def send_email(recipient, subject, msg):
   GMAIL_ID = 'your_email_here'
   GMAIL_PWD = 'your_password_here'

   email = EmailMessage()
   email['Subject'] = subject
   email['From'] = GMAIL_ID
   email['To'] = recipient
   email.set_content(msg)

   with smtplib.SMTP_SSL('smtp.gmail.com', 465) as gmail_obj:
       gmail_obj.ehlo()
       gmail_obj.login(GMAIL_ID, GMAIL_PWD)
       gmail_obj.send_message(email)
   print('Email sent to ' + str(recipient) + ' with Subject: \''
         + str(subject) + '\' and Message: \'' + str(msg) + '\'')


def send_bday_emails(bday_file):
   bdays_df = pd.read_excel(bday_file)
   today = datetime.now().strftime('%m-%d')
   year_now = datetime.now().strftime('%Y')
   sent_index = []

   for idx, item in bdays_df.iterrows():
       bday = item['Birthday'].to_pydatetime().strftime('%m-%d')
       if (today == bday) and year_now not in str(item['Last Sent']):
           msg = 'Happy Birthday ' + str(item['Name'] + '!!')
           send_email(item['Email'], 'Happy Birthday', msg)
           sent_index.append(idx)

   for idx in sent_index:
       bdays_df.loc[bdays_df.index[idx], 'Last Sent'] = str(year_now)

   bdays_df.to_excel(bday_file, index=False)


if __name__ == '__main__':
   send_bday_emails(bday_file='your_bdays_list.xlsx')

Site Connectivity Checker

This Python project uses the urllib and tkinter modules to test website connectivity.

We’ve used the tkinter module to create a GUI allowing users to enter a web address. Much like our previous examples, this includes labels, buttons, and entry fields.

After we’ve collected the user’s web address, we pass this to our user-defined function to return an HTTP status code for the current website via the urllib module’s .getcode() function.

For this example, we simply determine whether the HTTP code is 200. If it is, we know the site is working; otherwise, we inform the user that it is unavailable.

You could expand this code to consider a more granular approach to handling the various HTTP response codes, so feel free to add this!

Source Code:

'''
Site Connectivity Checker
-------------------------------------------------------------
Enter websites as http(s)://www.yourwebsite.com
'''


import urllib.request
import tkinter as tk


def test_connectivity():
  window = tk.Tk()
  window.geometry('600x400')
  head = tk.Label(window, text='Website Connectivity Checker',
                  font=('Calibri 15'))
  head.pack(pady=20)

  def check_url():
      web = (url.get())
      status_code = urllib.request.urlopen(web).getcode()
      website_is_up = status_code == 200

      if website_is_up:
          tk.Label(window, text='Website Available',
                   font=('Calibri 15')).place(x=260, y=200)
      else:
          tk.Label(window, text='Website Not Available',
                   font=('Calibri 15')).place(x=260, y=200)

  url = tk.StringVar()
  tk.Entry(window, textvariable=url).place(x=200, y=80, height=30, width=280)
  tk.Button(window, text='Check', command=check_url).place(x=285, y=150)
  window.mainloop()


if __name__ == '__main__':
  test_connectivity()

Language Detector

This Python project uses the langdetect module (see pip install instructions) to help us identify the language that has been entered. This can be really useful if you’re unsure which language you’re dealing with. 

This is another example where we’ve used tkinter to create a simple GUI involving labels, buttons, and an entry field. We can then collect text from the entry field and process this with the langdetect to determine which language was entered. Finally, we print this result to the GUI to let the user know the result.

Note that the results returned by langdetect are abbreviated language codes. For example, if we enter English text, we will see ‘en’ as the return value.

Source Code:

'''
Language Detector
-------------------------------------------------------------
pip install langdetect
'''


from langdetect import detect
import tkinter as tk


def detect_lang():
   window = tk.Tk()
   window.geometry('600x400')
   head = tk.Label(window, text='Language Detector', font=('Calibri 15'))
   head.pack(pady=20)

   def check_language():
       new_text = text.get()
       lang = detect(str(new_text))
       tk.Label(window, text=lang, font=('Calibri 15')).place(x=260, y=200)

   text = tk.StringVar()
   tk.Entry(window, textvariable=text).place(
       x=200, y=80, height=30, width=280)
   tk.Button(window, text='Check Language',
             command=check_language).place(x=285, y=150)
   window.mainloop()


if __name__ == '__main__':
   detect_lang()

Text to Speech

This Python project uses a range of new libraries to convert an existing article into a playable mp3 file. You’ll need to install nltk (natural language toolkit), newspaper3k, and gtts (see pip install instructions).

You’ll see that the program is simple, as we simply pass in a URL for an article to convert, then let the function we’ve defined handle the text-to-speech conversion with our newly installed modules.

So, consider trying this out the next time you fancy turning an article into a playable podcast as it’s definitely one of the cool Python codes to copy! 

Source Code:

'''
Text To Speech
-------------------------------------------------------------
pip install nltk newspaper3k gtts
'''


import nltk
from newspaper import Article
from gtts import gTTS


def text_to_speech(url):
   article = Article(url)
   article.download()
   article.parse()
   nltk.download('punkt')
   article.nlp()
   article_text = article.text
   language = 'en'
   my_obj = gTTS(text=article_text, lang=language, slow=False)
   my_obj.save("read_article.mp3")


if __name__ == '__main__':
   text_to_speech(
       url='https://hackr.io/blog/top-tech-companies-hiring-python-developers'
   )

Text Editor

This fun Python project creates a GUI to simulate our very own text editor. This example also uses standard GUI components, including labels, buttons, and entry fields.

However, we’ve also added the ability to open and save files like a real text editor. If you’re new to file handling, this Python project is a great way to understand how to read-in and save files.

Experiment with the code below to solidify your understanding, and see if you can expand on this code to create other features you’re used to using with a text editor, like a ‘find word’ function.

Source Code:

'''
Text Editor
-------------------------------------------------------------
'''


import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename


def text_editor():
   def open_file():
       filepath = askopenfilename(
           filetypes=[('Text Files', '*.txt'), ('All Files', '*.*')]
       )

       if not filepath:
           return

       txt_edit.delete(1.0, tk.END)
       with open(filepath, 'r') as input_file:
           text = input_file.read()
           txt_edit.insert(tk.END, text)
       window.title(f'TextEditor - {filepath}')

   def save_file():
       filepath = asksaveasfilename(
           defaultextension='txt',
           filetypes=[('Text Files', '*.txt'), ('All Files', '*.*')],
       )

       if not filepath:
           return

       with open(filepath, 'w') as output_file:
           text = txt_edit.get(1.0, tk.END)
           output_file.write(text)
       window.title(f'Text Editor - {filepath}')

   window = tk.Tk()
   window.title('Text Editor')
   window.rowconfigure(0, minsize=800, weight=1)
   window.columnconfigure(1, minsize=800, weight=1)

   txt_edit = tk.Text(window)
   fr_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)
   btn_open = tk.Button(fr_buttons, text='Open', command=open_file)
   btn_save = tk.Button(fr_buttons, text='Save As...', command=save_file)

   btn_open.grid(row=0, column=0, sticky='ew', padx=5, pady=5)
   btn_save.grid(row=1, column=0, sticky='ew', padx=5)

   fr_buttons.grid(row=0, column=0, sticky='ns')
   txt_edit.grid(row=0, column=1, sticky='nsew')

   window.mainloop()


if __name__ == '__main__':
  text_editor()

Data Structures & Algorithms

Binary Search Algorithm

It’s a rite of passage for all aspiring coders to tackle Binary Search in one of their Python programming projects at some point! I know when I was starting out, some of my most common Python mistakes involved classic algorithms like this.

This Python project for binary search takes in a sorted list (array), then continually compares a search value with the middle of the array.

Depending on whether the search value is less than or greater than the middle value, the list is split (divide and conquer strategy) to reduce the search space, which hones in on the given search value. This continual division results in logarithmic time complexity.

If you look at the code below, you’ll see that we’ve implemented two solutions: conditional loops and recursion. Both approaches are elegant, so feel free to experiment with each.

If you’re new to recursion, this is a great introduction as it demonstrates how we ‘reduce’ the size of the problem with each recursive call, namely by splitting the list to one side of the current middle element.

We’ve also defined the recursive base case as the point when the middle element equals the search element. In this case, the recursion will stop and return the True value up through the call stack.

If this all sounds alien to you, consider using something like GitHub Copilot to make more sense of this classic algorithm.

Source Code:

'''
Binary Search
-------------------------------------------------------------
'''


def binary_search(a_list, an_item):
   first = 0
   last = len(a_list) - 1

   while first <= last:
       mid_point = (first + last) // 2
       if a_list[mid_point] == an_item:
           return True
       else:
           if an_item < a_list[mid_point]:
               last = mid_point - 1
           else:
               first = mid_point + 1
   return False


def binary_search_rec(a_list, first, last, an_item):
   if len(a_list) == 0:
       return False
   else:
       mid_point = (first + last) // 2
       if a_list[mid_point] == an_item:
           return True
       else:
           if an_item < a_list[mid_point]:
               last = mid_point - 1
               return binary_search_rec(a_list, first, last, an_item)
           else:
               first = mid_point + 1
               return binary_search_rec(a_list, first, last, an_item)


if __name__ == '__main__':
   a_list = [1, 4, 7, 10, 14, 19, 102, 2575, 10000]
  
   print('Binary Search:', binary_search(a_list, 4))
   print('Binary Search Recursive:',
       binary_search_rec(a_list, 0, len(a_list) -1, 4))

Merge Sort Algorithm

Merge Sort is another popular coding challenge faced by aspiring coders when looking for things to do in Python.

This divide-and-conquer strategy uses division to separate a list of numbers into equal parts, and these are then recursively sorted before being recombined to generate a sorted list.

If you’ve just completed the Binary Search example, you might notice some similarities with division and reducing a problem’s size. You’d be right, which means you’ve likely realized we need to use recursion.

This Python implementation of Merge Sort uses recursion to handle the divide and conquer process. The continual reduction of the problem size allows the problem to be solved when the recursive base case is reached, namely when the problem size is one element or less.

In essence, this Python program continues to recursively divide the list until it reaches the base case. At this point it begins sorting the smaller parts of the problem, resulting in smaller sorted arrays that are recombined to eventually generate a fully sorted array. If you’re familiar with Big O notation, you’ll be curious to know that Merge Sort has a Big O of (n logn).

Source Code:

'''
Merge Sort
-------------------------------------------------------------
'''


def merge_sort(a_list):
   print("Dividing ", a_list)
  
   if len(a_list) > 1:
       mid_point = len(a_list)//2
       left_half = a_list[:mid_point]
       right_half = a_list[mid_point:]

       merge_sort(left_half)
       merge_sort(right_half)

       i=0
       j=0
       k=0

       while i < len(left_half) and j < len(right_half):
           if left_half[i] <= right_half[j]:
               a_list[k] = left_half[i]
               i += 1
           else:
               a_list[k] = right_half[j]
               j += 1
           k += 1

       while i < len(left_half):
           a_list[k] = left_half[i]
           i += 1
           k += 1

       while j < len(right_half):
           a_list[k] = right_half[j]
           j += 1
           k += 1
  
   print("Merging ", a_list)


if __name__ == '__main__':
   a_list = [45, 7, 85, 24, 60, 25, 38, 63, 1]
   merge_sort(a_list)
   print(a_list)

Queue

This Python project creates a new class to implement a Queue. This is a common data structure in computer science when you need to handle First-In-First-Out (FIFO) scenarios, such as message queues, CPU tasks, etc.

The code is straightforward and offers some more practice with object-oriented programming. Test out the queue to get your head around how it works, and then you’ll be ready to use this data structure in your other projects.

Source Code:

'''
Queue Data Structure
-------------------------------------------------------------
'''


class Queue:

   def __init__(self):
       self.items = []

   def __repr__(self):
       return f'Queue object: data={self.items}'

   def is_empty(self):
       return not self.items

   def enqueue(self, item):
       self.items.append(item)

   def dequeue(self):
       return self.items.pop(0)

   def size(self):
       return len(self.items)

   def peek(self):
       return self.items[0]


if __name__ == '__main__':
   q = Queue()
   print(q.is_empty())
   q.enqueue('First')
   q.enqueue('Second')
   print(q)
   print(q.dequeue())
   print(q)
   print(q.size())
   print(q.peek())

Sudoku Solver

This Python project uses the pygame library (see pip install instructions) to implement a GUI for automatically solving sudoku puzzles. We use several user-defined functions to create the GUI, as shown below.

To solve a sudoku puzzle, this program uses a backtracking algorithm that incrementally checks for solutions, either adopting or abandoning the current solution if it’s not viable.

This step of abandoning a solution is the defining feature of a backtracking approach, as the program steps back to try a new solution until it finds a valid one. This process is incrementally carried out until the entire grid has been correctly filled.

Feel free to experiment with different sudoku problems, and even think about expanding the size of the problem grid (you’ll need a new base image if you do this).

Source Code:

'''
Sudoku Solver
-------------------------------------------------------------
pip install pygame
image link:
https://www.pngitem.com/pimgs/m/210-2106648_empty-sudoku-grid-grid-6x6-png-transparent-png.png
'''


import pygame


pygame.font.init()
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption('SUDOKU SOLVER USING BACKTRACKING')
img = pygame.image.load('icon.png')
pygame.display.set_icon(img)
font1 = pygame.font.SysFont('comicsans', 40)
font2 = pygame.font.SysFont('comicsans', 20)
x = 0
y = 0
dif = 500 / 9
val = 0

# Default Sudoku Board
grid = [
   [7, 8, 0, 4, 0, 0, 1, 2, 0],
   [6, 0, 0, 0, 7, 5, 0, 0, 9],
   [0, 0, 0, 6, 0, 1, 0, 7, 8],
   [0, 0, 7, 0, 4, 0, 2, 6, 0],
   [0, 0, 1, 0, 5, 0, 9, 3, 0],
   [9, 0, 4, 0, 6, 0, 0, 0, 5],
   [0, 7, 0, 3, 0, 0, 0, 1, 2],
   [1, 2, 0, 0, 0, 7, 4, 0, 0],
   [0, 4, 9, 2, 0, 6, 0, 0, 7]
]


def get_coord(pos):
   x = pos[0] // dif
   y = pos[1] // dif


def draw_box():
   for i in range(2):
       pygame.draw.line(screen, (255, 0, 0), (x * dif-3, (y + i)
                        * dif), (x * dif + dif + 3, (y + i)*dif), 7)
       pygame.draw.line(screen, (255, 0, 0), ((x + i) * dif,
                        y * dif), ((x + i) * dif, y * dif + dif), 7)


def draw():
   for i in range(9):
       for j in range(9):
           if grid[i][j] != 0:
               pygame.draw.rect(screen, (0, 153, 153),
                                (i * dif, j * dif, dif + 1, dif + 1))
               text1 = font1.render(str(grid[i][j]), 1, (0, 0, 0))
               screen.blit(text1, (i * dif + 15, j * dif + 15))

   for i in range(10):
       if i % 3 == 0:
           thick = 7
       else:
           thick = 1
       pygame.draw.line(screen, (0, 0, 0), (0, i * dif),
                        (500, i * dif), thick)
       pygame.draw.line(screen, (0, 0, 0), (i * dif, 0),
                        (i * dif, 500), thick)


def draw_val(val):
   text1 = font1.render(str(val), 1, (0, 0, 0))
   screen.blit(text1, (x * dif + 15, y * dif + 15))


def raise_error_1():
   text1 = font1.render('WRONG !!!', 1, (0, 0, 0))
   screen.blit(text1, (20, 570))


def raise_error_2():
   text1 = font1.render('Wrong !!! Not a valid Key', 1, (0, 0, 0))
   screen.blit(text1, (20, 570))


def valid(m, i, j, val):
   for it in range(9):
       if m[i][it] == val:
           return False
       if m[it][j] == val:
           return False

   it = i // 3
   jt = j // 3

   for i in range(it * 3, it * 3 + 3):
       for j in range(jt * 3, jt * 3 + 3):
           if m[i][j] == val:
               return False
   return True


def solve(grid, i, j):
   while grid[i][j] != 0:
       if i < 8:
           i += 1
       elif i == 8 and j < 8:
           i = 0
           j += 1
       elif i == 8 and j == 8:
           return True

   pygame.event.pump()
   for it in range(1, 10):
       if valid(grid, i, j, it) == True:
           grid[i][j] = it
           x = i
           y = j
           screen.fill((255, 255, 255))
           draw()
           draw_box()
           pygame.display.update()
           pygame.time.delay(20)

           if solve(grid, i, j) == 1:
               return True
           else:
               grid[i][j] = 0
           screen.fill((255, 255, 255))

           draw()
           draw_box()
           pygame.display.update()
           pygame.time.delay(50)
   return False


def instruction():
  text1 = font2.render(
      'PRESS D TO RESET TO DEFAULT / R TO EMPTY\n', 1, (0, 0, 0))
  text2 = font2.render(
      'ENTER VALUES AND PRESS ENTER TO VISUALIZE\n', 1, (0, 0, 0))
  screen.blit(text1, (20, 520))
  screen.blit(text2, (20, 540))


def result():
  text1 = font1.render('FINISHED PRESS R or D\n', 1, (0, 0, 0))
  screen.blit(text1, (20, 570))


run = True
flag_1 = 0
flag_2 = 0
rs = 0
error = 0
while run:
   screen.fill((255, 255, 255))
   for event in pygame.event.get():
       if event.type == pygame.QUIT:
           run = False
       if event.type == pygame.MOUSEBUTTONDOWN:
           flag_1 = 1
           pos = pygame.mouse.get_pos()
           get_coord(pos)
       if event.type == pygame.KEYDOWN:
           if event.key == pygame.K_LEFT:
               x -= 1
               flag_1 = 1
           if event.key == pygame.K_RIGHT:
               x += 1
               flag_1 = 1
           if event.key == pygame.K_UP:
               y -= 1
               flag_1 = 1
           if event.key == pygame.K_DOWN:
               y += 1
               flag_1 = 1
           if event.key == pygame.K_1:
               val = 1
           if event.key == pygame.K_2:
               val = 2
           if event.key == pygame.K_3:
               val = 3
           if event.key == pygame.K_4:
               val = 4
           if event.key == pygame.K_5:
               val = 5
           if event.key == pygame.K_6:
               val = 6
           if event.key == pygame.K_7:
               val = 7
           if event.key == pygame.K_8:
               val = 8
           if event.key == pygame.K_9:
               val = 9
           if event.key == pygame.K_RETURN:
               flag_2 = 1

           # If R pressed clear sudoku board
           if event.key == pygame.K_r:
               rs = 0
               error = 0
               flag_2 = 0
               grid = [
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0],
                   [0, 0, 0, 0, 0, 0, 0, 0, 0]
               ]

           # If D pressed reset board to default
           if event.key == pygame.K_d:
               rs = 0
               error = 0
               flag_2 = 0
               grid = [
                   [7, 8, 0, 4, 0, 0, 1, 2, 0],
                   [6, 0, 0, 0, 7, 5, 0, 0, 9],
                   [0, 0, 0, 6, 0, 1, 0, 7, 8],
                   [0, 0, 7, 0, 4, 0, 2, 6, 0],
                   [0, 0, 1, 0, 5, 0, 9, 3, 0],
                   [9, 0, 4, 0, 6, 0, 0, 0, 5],
                   [0, 7, 0, 3, 0, 0, 0, 1, 2],
                   [1, 2, 0, 0, 0, 7, 4, 0, 0],
                   [0, 4, 9, 2, 0, 6, 0, 0, 7]
               ]

   if flag_2 == 1:
       if solve(grid, 0, 0) == False:
           error = 1
       else:
           rs = 1
       flag_2 = 0

   if val != 0:
       draw_val(val)
       if valid(grid, int(x), int(y), val) == True:
           grid[int(x)][int(y)] = val
           flag_1 = 0
       else:
           grid[int(x)][int(y)] = 0
           raise_error_2()
       val = 0

   if error == 1:
       raise_error_1()
   if rs == 1:
       result()
   draw()
   if flag_1 == 1:
       draw_box()
   instruction()

   pygame.display.update()

Bot Projects

Reddit Bot

This Python project creates an automated Reddit bot with some new modules, namely praw and enchant (see the pip install commands).

This is a fairly simple concept as the program checks every comment in a selected subreddit and then replies to any comments that contain a predefined ‘trigger phrase’. To do this, we use the praw module to interact with Reddit, and enchant to generate similar words to the comment, allowing us to make an appropriate reply.

This idea is really useful if you’re looking for Python projects to learn how to answer questions in your own subreddit. You’d just need to expand this code to include automated responses for predefined questions (you’ve probably already noticed this being used by others on Reddit!). 

Important note: You’ll need to check out these instructions to get hold of a client_id, client_secret, username, password, and user_agent. You’ll need this information to make comments to Reddit via the API interface.

Source Code:

'''
Reddit Reply Bot
-------------------------------------------------------------
pip install praw pyenchant
'''


import praw
import enchant


def reddit_bot(sub, trigger_phrase):
   reddit = praw.Reddit(
       client_id='your_client_id',
       client_secret='your_client_secret',
       username='your_username',
       password='your_pw',
       user_agent='your_user_agent'
   )

   subreddit = reddit.subreddit(sub)
   dict_suggest = enchant.Dict('en_US')

   for comment in subreddit.stream.comments():
       if trigger_phrase in comment.body.lower():
           word = comment.body.replace(trigger_phrase, '')
           reply_text = ''
           similar_words = dict_suggest.suggest(word)
           for similar in similar_words:
               reply_text += (similar + ' ')
           comment.reply(reply_text)


if __name__ == '__main__':
   reddit_bot(sub='Python', trigger_phrase='useful bot')

Chatbot

This Python project uses the chatterbot module (see pip install instructions below) to train an automated chatbot to answer any question you ask! I know; we’re now using AI!

You’ll see that the program is one of the relatively small Python projects in this list, but feel free to explore the ChatterBot documentation along with the broader field of AI chatbots if you’d like to learn more or expand the code’s features.

If this has whet your appetite for building AI bots, check out our 24-Hour Python Chatbot course to learn how to build an AI-powered chatbot with the same tools that power OpenAI’s ChatGPT.

And if you're hungry for even more AI goodness, check out OpenAI,'s latest feature that lets you build your own GPT.

Important note: ChatterBot is no longer being actively maintained. This means you need to make a small change to the tagging.py file located in the ‘Lib/site-packages/chatterbot’ directory of your Python installation folder.

Don’t worry; it’s straightforward to do, and we’ve included the exact source code you need to use, as shown below.

Source Code:

'''
Chat Bot
-------------------------------------------------------------
1) pip install ChatterBot chatterbot-corpus spacy
2) python3 -m spacy download en_core_web_sm
   Or... choose the language you prefer
3) Navigate to your Python3 directory
4) Modify Lib/site-packages/chatterbot/tagging.py
  to properly load 'en_core_web_sm'
'''


from chatterbot import ChatBot
from chatterbot.trainers import ChatterBotCorpusTrainer


def create_chat_bot():
   chatbot = ChatBot('Chattering Bot')
   trainer = ChatterBotCorpusTrainer(chatbot)
   trainer.train('chatterbot.corpus.english')

   while True:
       try:
           bot_input = chatbot.get_response(input())
           print(bot_input)

       except (KeyboardInterrupt, EOFError, SystemExit):
           break


if __name__ == '__main__':
   create_chat_bot()

Modify tagging.py:

Find the first code snippet, which is part of the __init__ method for the PosLemmaTagger class. Replace this with the if/else statement.

Note: this example is for the English library we used in our example, but feel free to switch this out to another language if you’d prefer.

# Replace this:
self.nlp = spacy.load(self.language.ISO_639_1.lower())

# With this:
if self.language.ISO_639_1.lower() == 'en':
   self.nlp = spacy.load('en_core_web_sm')
else:
   self.nlp = spacy.load(self.language.ISO_639_1.lower())

Advanced Python Projects

Library Management System

As one of the more advanced Python projects, this program uses object-oriented programming to simulate a library management system.

In this example, we create a Library and Student class, which we can use to create our library system and its users. We’ve then implemented a simple user interface that asks users to select from a range of standard library actions, like borrowing or returning books. 

This is a simple yet powerful example of how you can build out real-world systems via Python and object-oriented programming. Feel free to expand the classes to include other useful features, like unique book IDs, multiple copies of the same book, return dates, fees for returning books late, or any other features you think a library should have!

Source Code:

'''
Library
-------------------------------------------------------------
'''


class Library:

   def __init__(self, books):
       self.books = books

   def show_avail_books(self):
       print('Our Library Can Offer You The Following Books:')
       print('================================================')
       for book, borrower in self.books.items():
           if borrower == 'Free':
               print(book)

   def lend_book(self, requested_book, name):
       if self.books[requested_book] == 'Free':
           print(
               f'{requested_book} has been marked'
               f' as \'Borrowed\' by: {name}')
           self.books[requested_book] = name
           return True
       else:
           print(
               f'Sorry, the {requested_book} is currently'
               f' on loan to: {self.books[requested_book]}')
           return False

   def return_book(self, returned_book):
       self.books[returned_book] = 'Free'
       print(f'Thanks for returning {returned_book}')


class Student:
   def __init__(self, name, library):
       self.name = name
       self.books = []
       self.library = library

   def view_borrowed(self):
       if not self.books:
           print('You haven\'t borrowed any books')
       else:
           for book in self.books:
               print(book)

   def request_book(self):
       book = input(
           'Enter the name of the book you\'d like to borrow >> ')
       if self.library.lend_book(book, self.name):
           self.books.append(book)

   def return_book(self):
       book = input(
           'Enter the name of the book you\'d like to return >> ')
       if book in self.books:
           self.library.return_book(book)
       else:
           print('You haven\'t borrowed that book, try another...')


def create_lib():
   books = {
       'The Last Battle': 'Free',
       'The Hunger Games': 'Free',
       'Cracking the Coding Interview': 'Free'
   }
   library = Library(books)
   student_example = Student('Your Name', library)

   while True:
       print('''
           ==========LIBRARY MENU===========
           1. Display Available Books
           2. Borrow a Book
           3. Return a Book
           4. View Your Books
           5. Exit'''
             )

       choice = int(input('Enter Choice: '))
       if choice == 1:
           print()
           library.show_avail_books()
       elif choice == 2:
           print()
           student_example.request_book()
       elif choice == 3:
           print()
           student_example.return_book()
       elif choice == 4:
           print()
           student_example.view_borrowed()
       elif choice == 5:
           print('Goodbye')
           exit()


if __name__ == '__main__':
   create_lib()

Netflix Recommendation System

To cap it all off, we’ve saved a particularly exciting Python project for last! This is a Netflix recommendation system, ideal for aspiring data scientists. In fact, if you’re considering a machine learning course, this is a great project to reinforce your new skills.

To create this project, you’ll need to import a range of modules, including tkinter, re, nltk, pandas, and numpy (see pip install instructions for new modules). You’ll also need to download a Kaggle dataset containing Netflix movies and TV shows. 

We’ll use tkinter to create our GUI, which will use labels, buttons, and entry fields. The user will then be able to enter a TV show or movie they enjoyed on Netflix to return recommendations based on their taste. 

The recommendation engine uses cast, director, ratings, country, and genres as machine learning (ML) ‘features’. The code then uses the ‘cosine similarity’ approach to find similar results based on user input. This extensively uses pandas and numpy to clean the data and prepare it for processing.

There is a lot to unpack in this example, as it uses lots of Python concepts for data science.

The best approach is to slowly work through the code and then carry out further research on Machine Learning (ML), ‘features’, and ‘cosine similarity’. 

You’ll then be able to understand how to use a dataset to derive recommendations based on similarities. If you’re an aspiring data scientist, this is a terrific project to get your feet wet!

Source Code:

'''
Netflix Recommendation Engine
-------------------------------------------------------------
pip install pandas numpy nltk
'''


from nltk.tokenize import word_tokenize
import numpy as np
import pandas as pd
import re
import nltk
import tkinter as tk
from nltk.corpus import stopwords
nltk.download('stopwords')

data = pd.read_csv('netflixData.csv')
data = data.dropna(subset=['Cast', 'Production Country', 'Rating'])
movies = data[data['Content Type'] == 'Movie'].reset_index()
movies = movies.drop(['index', 'Show Id', 'Content Type', 'Date Added',
                    'Release Date', 'Duration', 'Description'], axis=1)
movies.head()
tv = data[data['Content Type'] == 'TV Show'].reset_index()
tv = tv.drop(['index', 'Show Id', 'Content Type', 'Date Added',
            'Release Date', 'Duration', 'Description'], axis=1)
tv.head()
actors = []
for i in movies['Cast']:
   actor = re.split(r', \s*', i)
   actors.append(actor)
flat_list = []

for sublist in actors:
   for item in sublist:
       flat_list.append(item)

actors_list = sorted(set(flat_list))
binary_actors = [[0] * 0 for i in range(len(set(flat_list)))]
for i in movies['Cast']:
   k = 0
   for j in actors_list:
       if j in i:
           binary_actors[k].append(1.0)
       else:
           binary_actors[k].append(0.0)
       k += 1

binary_actors = pd.DataFrame(binary_actors).transpose()
directors = []
for i in movies['Director']:
   if pd.notna(i):
       director = re.split(r', \s*', i)
       directors.append(director)

flat_list_2 = []
for sublist in directors:
   for item in sublist:
       flat_list_2.append(item)

directors_list = sorted(set(flat_list_2))
binary_directors = [[0] * 0 for i in range(len(set(flat_list_2)))]
for i in movies['Director']:
   k = 0
   for j in directors_list:
       if pd.isna(i):
           binary_directors[k].append(0.0)
       elif j in i:
           binary_directors[k].append(1.0)
       else:
           binary_directors[k].append(0.0)
       k += 1

binary_directors = pd.DataFrame(binary_directors).transpose()
countries = []
for i in movies['Production Country']:
   country = re.split(r', \s*', i)
   countries.append(country)

flat_list_3 = []
for sublist in countries:
   for item in sublist:
       flat_list_3.append(item)

countries_list = sorted(set(flat_list_3))
binary_countries = [[0] * 0 for i in range(len(set(flat_list_3)))]
for i in movies['Production Country']:
   k = 0
   for j in countries_list:
       if j in i:
           binary_countries[k].append(1.0)
       else:
           binary_countries[k].append(0.0)
       k += 1

binary_countries = pd.DataFrame(binary_countries).transpose()
genres = []
for i in movies['Genres']:
   genre = re.split(r', \s*', i)
   genres.append(genre)

flat_list_4 = []
for sublist in genres:
   for item in sublist:
       flat_list_4.append(item)

genres_list = sorted(set(flat_list_4))
binary_genres = [[0] * 0 for i in range(len(set(flat_list_4)))]
for i in movies['Genres']:
   k = 0
   for j in genres_list:
       if j in i:
           binary_genres[k].append(1.0)
       else:
           binary_genres[k].append(0.0)
       k += 1

binary_genres = pd.DataFrame(binary_genres).transpose()
ratings = []
for i in movies['Rating']:
   ratings.append(i)

ratings_list = sorted(set(ratings))
binary_ratings = [[0] * 0 for i in range(len(set(ratings_list)))]
for i in movies['Rating']:
   k = 0
   for j in ratings_list:
       if j in i:
           binary_ratings[k].append(1.0)
       else:
           binary_ratings[k].append(0.0)
       k += 1

binary_ratings = pd.DataFrame(binary_ratings).transpose()
binary = pd.concat([binary_actors, binary_directors,
                  binary_countries, binary_genres], axis=1, ignore_index=True)
actors_2 = []
for i in tv['Cast']:
  actor2 = re.split(r', \s*', i)
  actors_2.append(actor2)

flat_list_5 = []
for sublist in actors_2:
   for item in sublist:
       flat_list_5.append(item)

actors_list_2 = sorted(set(flat_list_5))
binary_actors_2 = [[0] * 0 for i in range(len(set(flat_list_5)))]
for i in tv['Cast']:
   k = 0
   for j in actors_list_2:
       if j in i:
           binary_actors_2[k].append(1.0)
       else:
           binary_actors_2[k].append(0.0)
       k += 1

binary_actors_2 = pd.DataFrame(binary_actors_2).transpose()
countries_2 = []
for i in tv['Production Country']:
   country2 = re.split(r', \s*', i)
   countries_2.append(country2)

flat_list_6 = []
for sublist in countries_2:
   for item in sublist:
       flat_list_6.append(item)

countries_list_2 = sorted(set(flat_list_6))
binary_countries_2 = [[0] * 0 for i in range(len(set(flat_list_6)))]
for i in tv['Production Country']:
   k = 0
   for j in countries_list_2:
       if j in i:
           binary_countries_2[k].append(1.0)
       else:
           binary_countries_2[k].append(0.0)
       k += 1

binary_countries_2 = pd.DataFrame(binary_countries_2).transpose()
genres_2 = []
for i in tv['Genres']:
   genre2 = re.split(r', \s*', i)
   genres_2.append(genre2)

flat_list_7 = []
for sublist in genres_2:
   for item in sublist:
       flat_list_7.append(item)

genres_list_2 = sorted(set(flat_list_7))
binary_genres_2 = [[0] * 0 for i in range(len(set(flat_list_7)))]
for i in tv['Genres']:
   k = 0
   for j in genres_list_2:
       if j in i:
           binary_genres_2[k].append(1.0)
       else:
           binary_genres_2[k].append(0.0)
       k += 1

binary_genres_2 = pd.DataFrame(binary_genres_2).transpose()
ratings_2 = []
for i in tv['Rating']:
   ratings_2.append(i)

ratings_list_2 = sorted(set(ratings_2))
binary_ratings_2 = [[0] * 0 for i in range(len(set(ratings_list_2)))]
for i in tv['Rating']:
   k = 0
   for j in ratings_list_2:
       if j in i:
           binary_ratings_2[k].append(1.0)
       else:
           binary_ratings_2[k].append(0.0)
       k += 1

binary_ratings_2 = pd.DataFrame(binary_ratings_2).transpose()
binary_2 = pd.concat([binary_actors_2, binary_countries_2,
                    binary_genres_2], axis=1, ignore_index=True)

window = tk.Tk()
window.geometry('600x600')
head = tk.Label(window, text='Enter Movie / TV Show on Netflix For Recommendations', font=('Calibri 15'))
head.pack(pady=20)


def netflix_recommender(search):
   cs_list = []
   binary_list = []

   if search in movies['Title'].values:
       idx = movies[movies['Title'] == search].index.item()
       for i in binary.iloc[idx]:
           binary_list.append(i)

       point_1 = np.array(binary_list).reshape(1, -1)
       point_1 = [val for sublist in point_1 for val in sublist]
       for j in range(len(movies)):
           binary_list_2 = []
           for k in binary.iloc[j]:
               binary_list_2.append(k)
           point_2 = np.array(binary_list_2).reshape(1, -1)
           point_2 = [val for sublist in point_2 for val in sublist]
           dot_product = np.dot(point_1, point_2)
           norm_1 = np.linalg.norm(point_1)
           norm_2 = np.linalg.norm(point_2)
           cos_sim = dot_product / (norm_1 * norm_2)
           cs_list.append(cos_sim)

       movies_copy = movies.copy()
       movies_copy['cos_sim'] = cs_list
       results = movies_copy.sort_values('cos_sim', ascending=False)
       results = results[results['title'] != search]
       top_results = results.head(5)
       return (top_results)

   elif search in tv['Title'].values:
       idx = tv[tv['Title'] == search].index.item()
       for i in binary_2.iloc[idx]:
           binary_list.append(i)

       point_1 = np.array(binary_list).reshape(1, -1)
       point_1 = [val for sublist in point_1 for val in sublist]
       for j in range(len(tv)):
           binary_list_2 = []
           for k in binary_2.iloc[j]:
               binary_list_2.append(k)

           point_2 = np.array(binary_list_2).reshape(1, -1)
           point_2 = [val for sublist in point_2 for val in sublist]
           dot_product = np.dot(point_1, point_2)
           norm_1 = np.linalg.norm(point_1)
           norm_2 = np.linalg.norm(point_2)
           cos_sim = dot_product / (norm_1 * norm_2)
           cs_list.append(cos_sim)

       tv_copy = tv.copy()
       tv_copy['cos_sim'] = cs_list
       results = tv_copy.sort_values('cos_sim', ascending=False)
       results = results[results['Title'] != search]
       top_results = results.head(5)
       return (top_results)

   else:
       return ('Title not in dataset. Please check spelling.')


def call_recommender():
  subject = text.get()
  recommendation = netflix_recommender(subject)
  txt = ''
  for i in recommendation.iterrows():
      txt += 'Title: ' + str(i[1][0]) + '\n'
  tk.Label(window, text=txt, font=('Calibri 15')).place(x=195, y=150)


text = tk.StringVar()
tk.Entry(window, textvariable=text).place(x=200, y=80, height=30, width=280)
tk.Button(window, text='Find Recommendations',
         command=call_recommender).place(x=285, y=150)
window.mainloop()

Where To Start With Python

Today, we’re experiencing an ever-growing adoption of Artificial Intelligence (AI), Machine Learning (ML), and data science across the vast majority of business sectors. One of the main things these fields have in common is that they use the Python programming language in one way or another.

When it comes to learning Python in 2025, you have so many choices. Plus, if you'd prefer an in-depth and interactive learning experience, we’d also recommend our new Python course

What Should I Build Using Python?

This is a great question, especially if you’re brand new to coding in Python.

Well, first things first, you should know that there are so many Python applications in various disciplines, so you have lots of options.

Of course, Python has developed a solid reputation for data science, data analysis, machine learning, and AI, but it doesn’t end there.

It’s also really good when it comes to web development, thanks to popular web application frameworks like Django and Flask.

Equally, it’s also ideal for automating repetitive tasks, hence its origin as a scripting language.

To put it simply, you can build a lot with Python, but if you’re looking for inspiration, you’re in the right place!

That's why I put together these Python projects for you to get stuck into.

Wrapping Up

Building projects is the fastest way to learn—and now you have a list of real-world, portfolio-worthy ideas to work on.

Pick a project, start coding, and watch your Python skills grow. And remember, I’m always adding new projects, so bookmark this page and check back for more!

Happy coding!

Enjoyed tackling these Python projects and are ready to dive deeper into Python? Check out:

Our Python Masterclass - Python with Dr. Johns

References

1. Bureau of Labor Statistics, U.S. Department of Labor. Occupational Outlook Handbook, Software Developers [Internet]. [updated 2021 Sep 8; cited 2024 Jan 15]. Available from: https://www.bls.gov/ooh/computer-and-information-technology/software-developers.htm

2. apilayer. FIXER API - Pricing [Internet]. apilayer; [date unknown; cited 2024 Jan 15]. Available from: https://apilayer.com/marketplace/fixer-api#pricing

3. [no author]. OAuth2 Quick Start Example [Internet]. GitHub; [updated 2016 Apr 26; cited 2024 Jan 15]. Available from: https://github.com/reddit-archive/reddit/wiki/OAuth2-Quick-Start-Example#first-steps

4. Makhija, S. Netflix Movies and TV Shows 2021 [dataset]. Kaggle; 2021. Available from: https://www.kaggle.com/datasets/satpreetmakhija/netflix-movies-and-tv-shows-2021?resource=download

 
By Robert Johns

Technical Editor for Hackr.io | 15+ Years in Python, Java, SQL, C++, C#, JavaScript, Ruby, PHP, .NET, MATLAB, HTML & CSS, and more... 10+ Years in Networking, Cloud, APIs, Linux | 5+ Years in Data Science | 2x PhDs in Structural & Blast Engineering

View all post by the author

Subscribe to our Newsletter for Articles, News, & Jobs.

I accept the Terms and Conditions.

Disclosure: Hackr.io is supported by its audience. When you purchase through links on our site, we may earn an affiliate commission.

In this article

Learn More

Please login to leave comments

Akib Dewan

all codes has so many mistakes

4 years ago

Robert Johns

Thanks for pointing this out. If you take a look at our latest projects, they should be all bug-free.

1 year ago

Robert Johns

Thanks for pointing this out. If you take a look at our latest projects, they should be all bug-free.

1 year ago

Esther Ndosi

Thank you for all these cool projects. Its great to start a year with them. On the second project I think the attempts should be appended after the guess == rand_num as it always print 1 and i think it should be the lowest attempts the user has. thank you.

1 year ago

Robert Johns

Thanks for taking the time to build these projects and spotting that. The second project has been updated, check it out and see what you think.

1 year ago

Robert Johns

Thanks for taking the time to build these projects and spotting that. The second project has been updated, check it out and see what you think.

1 year ago

Akash Roy

Embarking on a Python journey with these hands-on projects feels like unlocking a treasure trove of coding adventures!

9 months ago