DEV Community

Cover image for QR code with Python in 7 lines of code
Techelopment
Techelopment

Posted on • Edited on

QR code with Python in 7 lines of code

Cover photo by Walls.io on Unsplash

It only takes 7 lines of Python code to generate and save a QR code.

Using the library qrcode helps us to quickly and clearly manage the various phases of QR code creation.

First of all, let's install the library:

pip install qrcode
Enter fullscreen mode Exit fullscreen mode

This is the basic code to generate a QR code (the famous 7 lines 🙂):

import qrcode 

#value to generate QR code
data = "https://techelopment.bio.link" 

#initialize a qr object
qr = qrcode.QRCode(version=3, box_size=10, border=3, 
                   error_correction=qrcode.constants.ERROR_CORRECT_H) 

#add the value to convert
qr.add_data(data) 

#generate the QR code
qr.make(fit=True) 

#generate and save the image
image = qr.make_image(fill_color="black", 
                    back_color= "white") 
image.save("techelopment_qr_code.png")
Enter fullscreen mode Exit fullscreen mode

Now that we know the minimal instructions for creating a QR code, let's integrate the script to make it a little more advanced 😎.

Script evolution to generate more types of QR codes (a little more than 7 lines 😄)

Let's now create a mini application that allows us to choose the type of QR code to create. We will then have to:

  1. Add user input reading (to tell our mini app what type of QR to create). We'll do this with a numbered list.
  2. Create functions that allow us to request information useful for generating the type of QR code chosen
  3. Generate the data (i.e. the text content) with the right syntax to input to the library qrcode. This will help us generate complex QR codes such as an event or a contact.

Below is the numbered list for choosing the type of QR code:

  1. text
  2. URL
  3. contact
  4. event
  5. phone call
  6. SMS
  7. e-mail
  8. Wi-Fi

The user will enter a number and will be asked for information to generate the chosen QR type.

Before moving on to the code, let's install the Pillow library to be able to open the QR code image generated directly from our mini app 😊:

pip install Pillow
Enter fullscreen mode Exit fullscreen mode

This is the code of our mini application:

there are smarter ways to write it in python but that's not the purpose of this article

import qrcode
from PIL import Image

def get_string_data(type):
    string_types = ["text", "URL"]
    string = input(f"Insert {string_types[type-1]}: ")
    return string

def get_v_Card():
    name = input("Name:")
    surname = input("Surname:")
    address = input("Address:")
    email = input("email:")
    phone = input("phone:")
    contact = (f"BEGIN:VCARD\n"
               f"VERSION:3.0\r\n"
               f"N:{surname};{name};\r\n"
               f"FN:{name} {surname} \r\n"
               f'ADR;TYPE=home;LABEL="{address}":;;{address};;;;\r\n'
               f"EMAIL;PREF;Work:{email}\r\n"
               f"TEL;TYPE=cell:{phone}\r\n"
               f"END:VCARD\r\n")
    return contact

def get_event():
    start_date = input("start date (yyyymmdd hhmm) - e.g.: 20241231 2330: ")
    end_date = input("end date (yyyymmdd hhmm): ")
    title = input("title: ")
    description = input("description: ")
    URL = input("URL (might be not supported): ")
    event = ('BEGIN:VCALENDAR\n'
           'VERSION:2.0\n'
           'PRODID:-//techelopment\n'
           'CALSCALE:GREGORIAN\n'
           'BEGIN:VTIMEZONE\n'
           'TZID:Europe/Rome\n'
           'LAST-MODIFIED:20240422T053451Z\n'
           'TZURL:https://www.tzurl.org/zoneinfo-outlook/Europe/Rome\n'
           'X-LIC-LOCATION:Europe/Rome\n'
           'BEGIN:DAYLIGHT\n'
           'TZNAME:CEST\n'
           'TZOFFSETFROM:+0100\n'
           'TZOFFSETTO:+0200\n'
           f'DTSTART:{start_date[0:8]}T{start_date[9:13]}00\n'
           'RULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU\n'
           'END:DAYLIGHT\n'
           'BEGIN:STANDARD\n'
           'TZNAME:CET\n'
           'TZOFFSETFROM:+0200\n'
           'TZOFFSETTO:+0100\n'
           f'DTSTART:{start_date[0:8]}T{start_date[9:13]}00\n'
           'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU\n'
           'END:STANDARD\n'
           'END:VTIMEZONE\n'
           'BEGIN:VEVENT\n'
           'DTSTAMP:20240925T150859Z\n'
           'UID:1727276914723-11137@techelopment\n'
           f'DTSTART;TZID=Europe/Rome:{start_date[0:8]}T{start_date[9:13]}00\n'
           f'DTEND;TZID=Europe/Rome:{end_date[0:8]}T{end_date[9:13]}00\n'
           f'SUMMARY:{title}\n'
           f'URL:{URL}\n'
           f'DESCRIPTION:{description}\n'
           'END:VEVENT\n'
           'END:VCALENDAR\n')
    return event

def get_phone_call():
    phone = input("phone number: ")
    return f"TEL:{phone}"

def get_SMS():
    phone_number = input("phone number: ")
    message = input("message: ")
    return f"SMSTO: {phone_number}:{message}"

def get_email():
    to = input("TO: ")
    cc = input("CC: ")
    subject = input("subject: ")
    body = input("body: ")
    return f"mailto:{to}?cc={cc}&subject={subject}&body={body}"

def get_Wi_Fi():
    encryption_types = ["nopass", "WPA", "WEP"]
    encryption = input("Encryption:\n"
                        "  1. None\n"
                        "  2. WPA/WPA2\n"
                        "  3. WEP\n"
                        "> ")
    encryption_type = encryption_types[int(encryption)-1]
    network_name = input("Wi-Fi name: ")
    password = input("password: ")

    return f"WIFI:T:{encryption_type};S:{network_name};P:{password};H:;;"

def getData(type):
    match type:
        case 1: #text
            return get_string_data(type)
        case 2: #URL
            return get_string_data(type)
        case 3: #contact (vCard)
            return get_v_Card()
        case 4: #event
            return get_event()
        case 5: #phone call
            return get_phone_call()
        case 6: #SMS
            return get_SMS()
        case 7: #write email
            return get_email()
        case 8: #connect to Wi-Fi
            return get_Wi_Fi()

        # In case there is no match
        case _:
            return -1

if __name__ == "__main__":
    #let's build an array to easily use our options
    data_label = ["text", "URL", "contact", "event", "phone_call", "SMS", "e-mail", "Wi-Fi" ]

    #list of commands to choose what type of QR code to create
    choice = input("Select the type of QR code to create:\n"
                       f"  1. {data_label[0]}\n"
                       f"  2. {data_label[1]}\n"
                       f"  3. {data_label[2]}\n"
                       f"  4. {data_label[3]}\n"
                       f"  5. {data_label[4]}\n"
                       f"  6. {data_label[5]}\n"
                       f"  7. {data_label[6]}\n"
                       f"  8. {data_label[7]}\n"
                       "> ")

    #value to generate the QR code for
    data = getData(int(choice))

    if data != -1:
        #initialization of a qr object
        qr = qrcode.QRCode(version=3, box_size=10, border=3,
                           error_correction=qrcode.constants.ERROR_CORRECT_H)

        #adding the value to convert
        qr.add_data(data)

        #generation of QR code
        qr.make(fit=True)

        #generation of the image
        image = qr.make_image(fill_color="black",
                            back_color="white")

        #naming the image with the type of QR code chosen as a suffix
        qr_type = data_label[int(choice) - 1]
        image_name = f"my_qr_code_{qr_type}.png"

        #saving the image
        image.save(image_name)

        print(f"QR code '{image_name}' created successfully")

        #Open the image in the default image viewer
        print("opening...")
        pil_img = Image.open(rf"{image_name}")
        #This method will display the image in the default program
        pil_img.show()
        print("you can view the QR code in your default editor 😊")
    else:
        print("invalid input")
Enter fullscreen mode Exit fullscreen mode

Here's a result...find out what it encodes 🎁

QR surprise 🎁


Follow me #techelopment

Medium: @techelopment
Dev.to: Techelopment
facebook: Techelopment
instagram: @techelopment
X: techelopment
telegram: @techelopment_channel
youtube: @techelopment
whatsapp: Techelopment

Top comments (1)

Collapse
 
martinbaun profile image
Martin Baun

Great read! Looking forward to more like these!