How to Create Web Apps with Python, HTML and Thonny
RSS to HTML via Python
Python is a glue. We can use it to join different elements of code together. As a language, Python is easy to learn, and human readable which makes it one of the most effective languages for learning and general purpose programming. Part of Python’s charm are the many modules of code which can be easily inserted into a project.
Thonny is a powerful yet simple editor for Python and, with the release of version 4, we wanted to use it to create a project. In this how to we shall use the latest version of Thonny to create a web application that will pull Raspberry Pi stock data from rpilocator.com and use it to populate a table in our app.
RSS is a great way to share a stream of information. It can be used to serve news headlines, such as the Tom’s Hardware RSS feed or even the latest xkcd comic strip.
Nore that the RSS feed from rpilocator is not as up-to-date as the data on rpilocator.com. Think of this project as more of a notification system, than a “sniping” tool.
Installing Thonny 4.0
Thonny is the default Python IDE on the Raspberry Pi, but it is not limited to just that machine. Thonny is also available for Windows, Mac and Linux machines, and it can be used to write Python and MicroPython for devices such as the Raspberry Pi Pico W and ESP32.
1. Open a browser to the Thonny homepage.
2. Select the download for your OS. For Windows, there are a few options to choose from. The first choice is which version of Python, we would recommend the latest (3.10 at the time of writing). Next is your choice of installing Thonny to your machine, or using a portable version. We recommend installing Thonny to your machine.
Stay On the Cutting Edge: Get the Tom's Hardware Newsletter
Get Tom's Hardware's best news and in-depth reviews, straight to your inbox.
3. Click on the downloaded file to start the installation.
4. Click on “More Info” to continue the installation. The new installation has a certificate that is relatively unknown and has yet to build up a reputation.
5. Click on “Run anyway” to continue.
6. Click next to continue.
7. Accept the License agreement.
8. Select the checkbox to create a desktop icon. This is an optional step, We chose not to do this as we prefer icons in the task bar.
9. Click Install to start the install process.
10. Click Finish to end the installation.
Creating Our Project with Thonny 4.0
Thonny is beginner focused, but don’t be fooled, Thonny is a competent and fully featured editor for makers. Thonny has a multi-window layout that can be edited to suit your needs.
1. Files: This is a basic file manager that can be used to open files in a project. Raspberry Pi Pico W and other MicroPython devices will open an additional pane that we can use to copy files to and from the device.
2. Coding Area: Here is where we create the project for our code. We can have multiple tabs, for multiple files.
3. Python Shell: The Python Shell (REPL, Read, Eval, Print, Loop) is where we can see the output of our code, and also interact with it.
4. Assistant: If your code has a bug, or doesn’t follow a styling guideline, it will be flagged here.
Installing Modules with Thonny
Python modules (sometimes also referred to as “libraries”) are pre-written segments of code that enable extra functionality. Popular examples include RPI.GPIO and GPIO Zero for the Raspberry Pi. Modules often abstract / simplify complex tasks. In our project we will use two modules. PyWebIO is a module to create HTML content using Python. It also creates a web server that we can use to quickly connect to our app. The second module is Feedparser, an RSS feed reader module that we shall use to read the rpilocator Raspberry Pi stock level feed.
1. Open Thonny and ensure that no projects are open.
2. Click on Tools >> Manage Packages. Thonny has a built-in GUI for the Python 3 package manager “pip”.
3. Search for pywebio.This is the module that we shall use to generate a web page using Python.
4. Click Install to download and install the module.
5. Repeat the previous steps, this time install feedparser. Feedparser is a Python module for RSS feeds.
6. Click Close to quit the dialog.
Writing the Project Code
Our goal is to create a Python project that will use the data from rpilocator’s RSS feed to populate a table. We will grab the current five entries and display them in an HTML table, created using Python.
1. In a new blank document, import two modules from pywebio. The first contains the code to start a simple web server. The pywebio.output module is used to generate HTML elements such as tables and hyperlinks.
from pywebio import start_server
from pywebio.output import *
2. Import the feedparser module.
import feedparser
3. Create a function called main.
def main():
4. Inside the function create an object, “stock” and use it to store the parsed output of the rpilocator RSS feed.
stock = feedparser.parse('https://rpilocator.com/feed/')
5. Create three empty lists, in_stock, in_stock_link and category. These will be used to store the data retrieved from the “stock” object containing the RSS data.
in_stock = []
in_stock_link = []
category = []
6. Create a for loop that will iterate five times.
for i in range(5):
7. Use “append” to add the stock status, link and category (reseller name) to the appropriate list. The RSS data stored in “stock” is a mixture of lists and dictionaries. For the data in a list we can use its numerical index, which is the value of i in our for loop. This will count from 0 to 4 as the for loop iterates. The data stored in a dictionary requires us to know the key (‘entries’ for example). Using the key will return its value.
in_stock.append(stock['entries'][i]['title'])
in_stock_link.append(stock['entries'][i]['link'])
category.append(stock['entries'][i]['category'])
8. Outside of the for loop, create a pop-up notification using “toast”. The message can be a mixture of a strong, and even emojis.
toast('🍓I found Raspberry Pi in stock!🍓')
9. Use “put_html” to write an HTML H1 heading element to the web page. We can use this function to write any HTML elements to the page, but do take note that the PyWebIO module has many different means to create specialist elements.
put_html("<h1>Raspberry Pi Stock</h1>")
10. Create a list, “table” and use it to store two columns of data, taken from our in_stock, in_stock_link and category lists. The first row are the column headings Details and URL. In stock will print a brief description of what is in stock. Using “put_link” we create an HTML hyperlink, with the link text being the name of the reseller, stored in the category list, and the address stored in in_stock_link.
table = [['Details','URL'],
[in_stock[0], put_link(category[0],url=in_stock_link[0])],
[in_stock[1], put_link(category[1],url=in_stock_link[1])],
[in_stock[2], put_link(category[2],url=in_stock_link[2])],
[in_stock[3], put_link(category[3],url=in_stock_link[3])],
[in_stock[4], put_link(category[4],url=in_stock_link[4])],
]
11. Use PyWebIO’s “put_table” function to create an HTML table from our table object.
put_table(table)
12. Use “put_link” to create a hyperlink under the table, in this case it takes us to the source of the Raspberry Pi stock levels, rpilocator.
put_link('Data provided by RPiLocator',url='https://rpilocator.com')
13. Outside of the function, call PyWebIO’s “start_server” function, and pass it three arguments. The arguments are our “main” function which will create the table from the RSS data. The port is set to 8080, and debugging is enabled via the Python shell and on our web page.
start_server(main, port=8080, debug=True)
14. Save the code as RSS-Feed-Reader.py and click Run to start.
15. Click on the link in the Python shell to open the web page in your default browser.
Complete Code Listing
from pywebio import start_server
from pywebio.output import *
import feedparser
def main():
stock = feedparser.parse('https://rpilocator.com/feed/')
in_stock = []
in_stock_link = []
category = []
for i in range(5):
in_stock.append(stock['entries'][i]['title'])
in_stock_link.append(stock['entries'][i]['link'])
category.append(stock['entries'][i]['category'])
toast('🍓I found Raspberry Pi in stock!🍓')
put_html("<h1>Raspberry Pi Stock</h1>")
table = [['Details','URL'],
[in_stock[0], put_link(category[0],url=in_stock_link[0])],
[in_stock[1], put_link(category[1],url=in_stock_link[1])],
[in_stock[2], put_link(category[2],url=in_stock_link[2])],
[in_stock[3], put_link(category[3],url=in_stock_link[3])],
[in_stock[4], put_link(category[4],url=in_stock_link[4])],
]
put_table(table)
put_link('Data provided by RPiLocator',url='https://rpilocator.com')
start_server(main, port=8080, debug=True)
Python How Tos
- How To Install Python on Windows 10 and 11
- How to use For Loops in Python
- How to Enumerate in Python
- How to Create Executable Applications in Python
- How To Remove Backgrounds From Images With Python
- How to Create Web Apps with Python, HTML and Thonny
- How To Use Raspberry Pi Camera Module 3 with Python Code
Les Pounder is an associate editor at Tom's Hardware. He is a creative technologist and for seven years has created projects to educate and inspire minds both young and old. He has worked with the Raspberry Pi Foundation to write and deliver their teacher training program "Picademy".
-
brandonjclark "Part of Python’s charm "Reply
PyCharm: the Python IDE for Professional Developers by JetBrains
I see what you did there... ;) -
Just use Microsoft code with the appropriate plug-ins. No need for that IDE at all especially if it’s not free. I use sublime text anyway for all my development purposes I don’t need any extra garbagebrandonjclark said:"Part of Python’s charm "
PyCharm: the Python IDE for Professional Developers by JetBrains
I see what you did there... ;)
Nobody needs a fancy IDE for python LOL
There editor looks just like Microsoft code which is based on Atom -
Bo-W4GHV Looked interesting, but way over my head, I gave it a try. I got the following errors and don't have a clue. I sent them to the feedparser author of possible help.Reply
I'm still at the beginner level trying to get cute graphics and menus on the screen with TKinter. :)
Traceback (most recent call last):
File "C:\Users\Bo\Downloads\Adafruit_CircuitPython_MatrixKeypad-main\examples\RSS-Feed-Reader.py", line 3, in <module>
import feedparser
File "C:\Users\Bo\AppData\Roaming\Python\Python310\site-packages\feedparser\init.py", line 39, in <module>
from . import api
File "C:\Users\Bo\AppData\Roaming\Python\Python310\site-packages\feedparser\api.py", line 54, in <module>
from . import http
File "C:\Users\Bo\AppData\Roaming\Python\Python310\site-packages\feedparser\http.py", line 44, in <module>
_base64decode = getattr(base64, 'decodebytes', base64.decodestring)
AttributeError: module 'base64' has no attribute 'decodestring'
73, Bo W4GHV since '54 -
MisterWho decodestring() does no longer exists from v3.9. Checkout this docs, use base64.decodebytes() instead.Reply -
Bo-W4GHV Thanks! Strangely the program had a comment to that change but failed to fix it!🤔Reply
Fixing it in 2 files fixed it and it 'ran'
However the web page results has a list of new errors!
I'll list them but don't worry/bother if fixing it is a mess.
Again over my head but looked like one I could get going. 73. Bo
Traceback (most recent call last):
File "C:\Users\Bo\AppData\Roaming\Python\Python310\site-packages\pywebio\session\threadbased.py", line 86, in main_task
target()
File "C:\Users\Bo\Downloads\Adafruit_CircuitPython_MatrixKeypad-main\examples\RSS-Feed-Reader.py", line 5, in main
stock = feedparser.parse('https://rpilocator.com/feed/')
File "C:\Users\Bo\AppData\Roaming\Python\Python310\site-packages\feedparser\api.py", line 238, in parse
data = convert_to_utf8(result, data, result)
File "C:\Users\Bo\AppData\Roaming\Python\Python310\site-packages\feedparser\encodings.py", line 244, in convert_to_utf8
if isinstance(proposed_encoding, collections.Callable):
AttributeError: module 'collections' has no attribute 'Callable' -
Bo-W4GHV
I traced down all the comments and it looks like the problem is with the https://rpilocator.com/feed error listed.Bo-W4GHV said:Thanks! Strangely the program had a comment to that change but failed to fix it!🤔
Fixing it in 2 files fixed it and it 'ran'
However the web page results has a list of new errors!
I'll list them but don't worry/bother if fixing it is a mess.
Again over my head but looked like one I could get going. 73. Bo
Traceback (most recent call last):
File "C:\Users\Bo\AppData\Roaming\Python\Python310\site-packages\pywebio\session\threadbased.py", line 86, in main_task
target()
File "C:\Users\Bo\Downloads\Adafruit_CircuitPython_MatrixKeypad-main\examples\RSS-Feed-Reader.py", line 5, in main
stock = feedparser.parse('https://rpilocator.com/feed/')
File "C:\Users\Bo\AppData\Roaming\Python\Python310\site-packages\feedparser\api.py", line 238, in parse
data = convert_to_utf8(result, data, result)
File "C:\Users\Bo\AppData\Roaming\Python\Python310\site-packages\feedparser\encodings.py", line 244, in convert_to_utf8
if isinstance(proposed_encoding, collections.Callable):
AttributeError: module 'collections' has no attribute 'Callable'
Headed there now. A 'RPI locator' will find about 6 of them here.😂 -
Bo-W4GHV
WAIT! How dumb I am. I actually have closer to 10 Pi's and need NO more.Bo-W4GHV said:I traced down all the comments and it looks like the problem is with the https://rpilocator.com/feed error listed.
Headed there now. A 'RPI locator' will find about 6 of them here.😂
I was thinking it could be easily modified to do for 'fun' /educational things.
I probably should quit this one.
Earlier I struck out just trying to scrape the solar data from https://www.hamqsl.com for a cute display.
I am succeeding in getting a Pi, tkinter,Python, arduino, stepper motor controlling a mag loop antenna. -
MisterWho Bo-W4GHV said:Thanks! Strangely the program had a comment to that change but failed to fix it!🤔
Fixing it in 2 files fixed it and it 'ran'
However the web page results has a list of new errors!
I'll list them but don't worry/bother if fixing it is a mess.
Again over my head but looked like one I could get going. 73. Bo
Traceback (most recent call last):
File "C:\Users\Bo\AppData\Roaming\Python\Python310\site-packages\pywebio\session\threadbased.py", line 86, in main_task
target()
File "C:\Users\Bo\Downloads\Adafruit_CircuitPython_MatrixKeypad-main\examples\RSS-Feed-Reader.py", line 5, in main
stock = feedparser.parse('https://rpilocator.com/feed/')
File "C:\Users\Bo\AppData\Roaming\Python\Python310\site-packages\feedparser\api.py", line 238, in parse
data = convert_to_utf8(result, data, result)
File "C:\Users\Bo\AppData\Roaming\Python\Python310\site-packages\feedparser\encodings.py", line 244, in convert_to_utf8
if isinstance(proposed_encoding, collections.Callable):
AttributeError: module 'collections' has no attribute 'Callable'
AttributeError: module 'collections' has no attribute 'Callable'
Removed from v3.10
In the article the author uses Thonny 4.0.0.
Thonny 4.0.0 comes with Python 3.10.6 - this script would've NEVER worked without any error! O.o