Notebooks are boring!
So you wrote your first scripts on a Jupyter Notebook and you frantically run every cell each time you want to use the script. It’s not very practical, is it? Sure, you can install some extensions and some widgets and I even came across an article where someone created a dashboard that was updated in real time inside the notebook. But wouldn’t it be cooler if you created your own program that you could start with a simple click? As a side project, I decided to make some videos **** about the code in my articles, so I would love to hear from you regarding the format, duration, and any other feedback! Thanks!
You will be able to build simple templates that can turn your old and future scripts into personalized tools!
A Graphical User Interface, also known as GUI, **** _is a form of user interface that allows users to interact with electronic devices through graphical icon_s. It’s a fancy term for what normal people call an "application". Unless you’re reading this from the command line (which actually would be a bit weird…), you are most likely using a GUI right now.
I like Jupyter notebooks because they’re easy to use and invite you to structure your code in separate cells. It’s arguably the best entry point for anyone new to Python and programming, but you’re going to need a bit more if you are serious about a career in Data Science. After a notebook is finished it’s easy to say "done" and move on to a different project, but what if you gave them their own interface? If the code is not too complex and it’s well structured, you can even use a simple template for every script like the one I share in this article.
For some time I was stuck with Jupyter notebooks when I wanted to work on any Python projects. I struggled to understand the framework behind working with .py files within a command prompt, but eventually, it clicked! And it happened a while ago when I was searching for Tkinter resources, so you can probably sense where I am going with this… No Jupyter notebooks will be used today! We’ll build this app using .py files and an IDE.
My articles are written with non-IT people in mind, so if that’s your case, no need to panick! I’ll hold your hand throughout the code and I try my best to answer every question in the comments
What you will be able to do with this Tkinter project:
- create a user interface to run your scripts
- ask the user some input in a text field and use it as a variable
- click buttons that run specific parts of your code
- ask the user to select a file to be used with a file dialog prompt
- bonus: move from working exclusively with Jupyter!

For this project, I am going to use my previous article as the source for a script to be used with our app. It’s a basic script that checks for flight prices from Kayak and compiles the results. It has a few inputs that were hardcoded, but as I mentioned, we want our experience to be more like a normal program so I had to tweak it a little bit. I explain it in the videos I created as a complement to the article. I strongly recommend you to have a look, as some details have to be cut from the article for the sake of brevity!
You will need a couple of things before proceeding:
- code editor: I will be using Spyder, which isn’t perfect but it’s decent enough. If you’re not sure what this means, try checking to see if you have IDLE installed. It is preinstalled with Python, so you should be fine here. fun fact: IDLE was built with Tkinter!
- packages: Obviously you will need to install Tkinter package. There are plenty of online resources to help you do this. But if you want to master it, I’ll leave a couple of recommended books in the end.
- modules: you will need the previous FlightScraper script updated to .py file which I share here. Get it and place it in the same folder you will work on.
Every program starts with a window
Tkinter may seem weird and difficult to understand at first, and that’s why I’ll build the code block by block trying to explain what we are creating and how it is displayed in the app. Assuming you have installed everything, simply create a folder for the project and create a file with the extension .py. Your first lines of code on that file should look like the ones below.
Every Tkinter app needs to be structured this way. We call the tk.Tk() to create the app window, and we then build our app and place the widgets (frames, buttons, labels, etc) where we want before "compiling" everything with window.mainloop(). I will not go into much detail about how Tkinter works, but if you want to understand what’s the loop and the basic structure to build an app, check their resources.
At this point, it’s probably better that we talk about the widgets we will need. And by the way, widgets are the elements of Tkinter (like buttons, labels, frames, entries, etc). I will use just a few, and if you get the basics with these, it’s really easy to go out there and test others by yourself.
- Frames: our app will be divided into three frames stacked on top of each other. The top frame will be used to place our header, while the bottom will display our app buttons. The frame in the middle will consist of two other frames (yes, you can place a widget inside another widget!)
- Grid: I will use Grid as one way to define the layout of the app. If you’re feeling adventurous feel free to try Place, which lets you set the position with specific x,y coordinates of the screen. In my opinion, Grid is the easiest to understand and to work with so we’ll be using that and Pack.
- Pack: it is also a layout manager and it’s really easy to understand… every time you use .pack() it will stack that widget under the previously packed one.
- Labels: simply put, they’re textboxes. We’ll use it in the header and next to the entry boxes.
- Entries: it’s the widget that lets the user write some kind of input like the cities and the dates.
- Buttons: do I really need to explain what a button is?! Jokes aside, there is an argument called command inside the button widgets that tells the button what function to run when it is pressed.
Now you know the ingredients, let’s look at the recipe
So lets jump right into it. Below is the code for the first three frames and the header. I used the grid method to place them in the app. You may have already noticed that the header is on top (row 0 and column 0), the center is… well in the center (1,0), and the bottom frame is below the center frame (2,0). I’ve added some arguments like border width and pady (padding y-axis) to make it look nicer. When we create the frames, we need to tell Tkinter which window they belong to, and we define that with passing the window variable (our main window) as the master for the frame. The key point here is that the argument master is used in every widget and that is what defines where the widget is placed.
We also place a label inside the header, hence passing _frameheader in the label widget. The process is the same for every widget. You create a variable with the widget you want, tell Tkinter where it belongs to, and then place it in the app. Since the _frameheader will only contain the header label, we place it in the position 0,0. Play around with the label arguments to understand your formatting options! This is a really nice resource for Tkinter and how to use the widgets, with examples.
Remember that the code above must be placed before window.mainloop(), otherwise the program won’t run
It is a good idea to save some time and frustration later to always test what you are doing. You may think you are placing everything in the perfect position, and when you run the file, it’s total madness. It happens! So we need to run the file now and then to see how the widgets are displaying. There’s no way around it. If you’re coming from Jupyter notebooks, don’t freak out just yet. The editor you are using probably has a way to run the files (hopefully Python files!). In Spyder you can use F5 directly in the editor and the console will run the code. In fact, most IDE’s have the same shortcut (F5) to run a file. It’s that easy… If you have the code as I showed you, and the mainloop() in the end, after you run it, a window should pop up. Congratulations, that’s the beginning of your first GUI!

It doesn’t look like much yet, but we’ll get there. If you’re paying attention to the code, I said I placed three frames, but only the header showed up… Yes, that was my first struggle with Tkinter. I didn’t realize the frames would only show up if they had some sort of elements there. Duh…! So we’ll take care of the rest of the frames next. You can close the app window and run the file as many times as you want.
Pack it before you check it
Let’s add two more frames inside the center frame, _frame_main1 and _frame_main2. While we’re at it, let’s also add the labels for those frames. I want to have an entry box for each one of the labels there. We’ll take care of that next.
Same logic for the labels as we did with the frames. We tell Tkinter the labels belong to frame 1 and 2, and what text they will display. The point of having a GUI is to let the user interact more fluently with the program, so we need to decide what we want the user to give us as inputs. If you remember the code from the other article, we need some strings to build our url, so essentially, we are expecting strings from the user. The lines below the labels are just that.

We are defining four variables to be StringVar(). It’s difficult to explain in simple terms but think of this kind of variable as an object that Tkinter will be able to track while the program runs. You can then create actions to be executed when specific events happen to these variables. They are still a string, but belong to a different breed!
I had to add the last lines with .pack() because otherwise, nothing would show up if we ran the program again. Feel free to leave the last lines out and run the program again. It will show the exact same box with just the header as before. I am telling you this at this point because these lines will not stay in this position later on since we need to add more widgets (and a few functions) before packing everything. The link to the whole code should be available in the last paragraph of the article!

Wait, there are functions too?!
I deliberately left the functions to a later stage, but they will have to be placed somewhere below the import statements and before the widgets part. Here are the four functions, two of which will be needed for our entry forms (to make the letters in the city entries to be upper case, and to limit the length to 3 characters). We will also have two buttons, one to run the bot, and another to exit the app. The _runapp function will be addressed later.
What do we want the user to input? Easy… We want them to type the cities (from and to), and the dates of the trip (departure and return). With this, the bot can do its thing. The third video covers this part!
I will need the functions _capsfrom and _capsto because we need to use them with the bind method in the Entry boxes. What .bind() does is to wait for an event to happen in the widget and run a sequence/function. In this case, the widget is the entry box, the event is a key release, and the function will limit the character length and transform the letters into upper case. Pretty simple, and I feel like this is a nice trick for your repertoire!
If you’re going snippet by snippet, simply replace the previous pack() statements in _tkinterapp3.py by the whole code in this snippet _tkinterapp5.py.

Where are the buttons?!
Yes, it’s time to get the buttons to show up in the app. We already took care of the function to exit the app. The command is called "destroy" which sounds super creepy and scary, but that’s what it does: it destroys the window! So, our _closeapp function is a single line, window.destroy(). The _runapp function we created before will simply print "run" in the console, so we will know it is working if we get a text saying "run".

This part can go directly below the last snippet, and the mainloop() will take care of the proper execution. So you can pack widgets, and then create a few more and pack them below. The important part is to keep track of the order you are using. Otherwise, it can get messy with more complex scripts.
The Button widget is easily mapped with a function in the argument "command=". Notice how I direct one to the _runapp function and the other to _closeapp. Oh, and the master for these buttons is the _bottomframe.
And voilá! The interface is complete. It looks rough, and the alignment could be better (to say the least), but hey… it’s your app, so go ahead and improve it!

This should give you the basics to build simple apps for your scripts, but we still need to link this project to our Flight Scraper script and redo the _runapp function to activate it with the "Start" button. Here’s how the _runapp function should look in the end. This function uses the method .get() on the entries and it will initiate our bot with Flight_Bot(). It then passes the user inputs to the function _startkayak that is part of the bot. You should be able to recognize its name from the previous article.
please note: in order to start the bot, you need to import it in the initial imports!! Check it out in the fourth video
I did this by adapting the script from the previous article (in a jupyter notebook) to a py file named flight_scraper_bot.py, and placing it in the same folder as the one we have been working on. From there, we can import it and use it within our program. That py file is available here. The line we need to add to our tkinter file is: _from flight_scraper_bot import FlightBot
That is already included in the final and compiled version of our script and I placed it here for you to grab it. It’s easier than copy and pasting multiple snippets throughout the article. You’re welcome!
I go over it in more detail in the videos, so definitely check them out if you need help. And like I mentioned in the beginning, your comments are really important to help me improve the quality of the articles and videos, so feel free to send your feedback and questions!
This [book](https://amzn.to/31rBwUH) had everything I needed to know whenever I was struggling with a particular widget. If you want to master Tkinter, I’m sure it can help you with that. And if you got interested in the Web Scraping part, this is the book I used to learn Selenium and others. (If you use this link, I receive a small fee at no extra cost to you. I do need a lot of coffee to write these articles!)

_Thank you for reading! If you liked this article, I invite you to check my other stories. I’m mainly interested in Data Science, Python, Blockchain and digital currencies, technology, and a few other things like photography!_
If you’d like to get in touch, you can contact me here or simply reply to the article below.