Planet Python
PyBites: 10 Tips to Make Your Developer Resume Stand Out
At Pybites we support our pythonistas with expert CV guidance to make their job applications stand out in a tight talent market
Here are some essential ingredients that make a great resume:
1. Clear and Concise Structure
Start with a clean, well-organized format. Use headers, bullet points, and consistent fonts to ensure readability.
2. Compelling Summary
Craft a short but powerful summary showcasing your passion for technology, your key skills, and what drives you professionally.
3. Tailored Content
Customize your resume for the job you’re applying to. Highlight relevant skills and experiences that match the job description.
4. Technical Skills
List your technical proficiencies. Include programming languages, software, tools, and certifications. Be honest about your skill level.
5. Quantify Achievements
Use numbers to illustrate your impact. Whether it’s reducing code errors, improving system efficiency, or increasing user engagement, quantify your achievements.
6. Experience
Detail your work experience, starting with the most recent role. Focus on accomplishments, not just duties. Describe how you contributed to projects and what you learned.
7. Projects and Side Hustles
Highlight personal projects, open-source contributions, or side gigs. They demonstrate your passion and initiative.
8. Education
Include your academic background, relevant coursework, and any honors or awards. Mentioning relevant coursework can be especially helpful for recent graduates.
9. Certifications and Training
Showcase relevant certifications, workshops, or courses you’ve completed. It proves your commitment to staying up-to-date.
10. Professional Presentation
Pay attention to grammar, spelling, and consistency. Typos can send the wrong message about your attention to detail.
Remember, your resume is a dynamic document that evolves with your career. Keep it updated and seek feedback from mentors or peers to continually improve.
Work with us in PDM (Pybites Developer Mindset) where we have you developer 2-3 applications that will boost your GitHub.
We also have a dedicated career coach that will make your resume / LinkedIn look a lot better so you’ll attract more work opportunities.
We were blown away by this nice feedback the other day by somebody that worked with her:
> It has been a month since I implemented the changes you recommended to both my Linkedin profile and my CV. The results have been fantastic! I have had more approaches by more people on LinkedIn in the last month than I had in the 3 months prior to that.
> On top of that whenever I have sent my CV out, I have had much better responses from people. I suspect my CV does not make people’s eyes glaze over anymore and keeping it to 2 pages and having all the recommendations you mentioned really makes it stand out.
So don’t hold off longer and take your Python career to the next level
Learn more about our PDM coachingStack Abuse: Difference Between del, remove, and pop in Python Lists
When working with lists in Python, you may often find the need to remove or modify elements. And, lucky for us, Python provides a couple methods to do just this, including del, remove, and pop. But why are there three ways to do this? Which one should we use, and why?
In this Byte, we'll explore how to use del and remove to modify lists, along with examples of each.
Using del to Modify ListsThe del statement in Python is a way to remove elements from a list based on their index. Unlike remove and pop, del is not a method of the list class, but a Python keyword. You can use del to remove a single element, or to remove a slice of elements. It also works on other Python data structures, like tuples and dictionaries.
Here's a basic syntax of using del:
del list[index]Where index is the position of the element you want to remove. Remember, Python list indices start at 0!
Examples of Using delLet's take a look at a few examples of using del to modify lists.
# Define a list fruits = ['apple', 'banana', 'cherry', 'date'] # Remove the second element del fruits[1] print(fruits) # Output: ['apple', 'cherry', 'date']In this example, we removed the second element ('banana') from the list. You can also use del to remove a slice of elements:
# Define a list numbers = [1, 2, 3, 4, 5, 6] # Remove the second through fourth elements del numbers[1:4] print(numbers) # Output: [1, 5, 6]Here, we removed the second through fourth elements (2, 3, and 4) from the list.
Using remove to Modify ListsThe remove() method removes the first occurrence of the specified value from the list. Unlike del, remove() doesn't work with indices, but with the actual values in the list.
Here's a basic syntax of using remove():
list.remove(element)Where element is the actual value you want to remove from the list.
Note: If the specified value doesn't exist in the list, remove() will raise a ValueError.
Examples of Using removeNow, let's see remove() in action.
# Define a list fruits = ['apple', 'banana', 'cherry', 'banana'] # Remove 'banana' fruits.remove('banana') print(fruits) # Output: ['apple', 'cherry', 'banana']In this example, remove() found the first occurrence of "banana" and removed it. Note that the second occurrence of "banana" is still in the list. To remove all occurrences of an element, you would need to use a loop or list comprehension.
Note: Always be careful when modifying a list while iterating over it, as this can cause unexpected behavior due to the changing indices of the elements.
# Define a list with multiple 'banana' fruits = ['apple', 'banana', 'cherry', 'banana'] # Remove all 'banana' fruits = [fruit for fruit in fruits if fruit != 'banana'] print(fruits) # Output: ['apple', 'cherry']In this example, we used list comprehension to create a new list that contains only the elements that are not 'banana'.
Using pop to Modify ListsThe pop() method is another way to modify lists in Python. This method is a bit different from del and remove because it not only removes an element from the list but also returns the removed item. This can be handy when you want to use the removed item later in your code.
The pop() method takes one argument, the index of the element you want to remove and return. If you don't provide an index, pop() will remove and return the last item in the list.
Here's the general syntax for the pop() method:
list.pop(index) Examples of Using popLet's see the pop() method in action. Suppose we have a list of integers:
numbers = [1, 2, 3, 4, 5]We can use pop() to remove and return the third item (index 2):
removed_item = numbers.pop(2) print(numbers) print(removed_item)The output will be:
[1, 2, 4, 5] 3As you can see, the number 3 was removed from the list and stored in the removed_item variable.
Comparing del, remove, and popNow that we've explored del, remove, and pop, let's do a quick comparison these three methods.
- del is a Python keyword, not a list method. It removes an item at a specific index and doesn't return anything.
- remove is a list method that removes the first occurrence of a specified value from the list. It also doesn't return anything.
- pop is a list method that removes an item at a specific index and returns that item.
Which one should you use? Well, of course, it depends on your needs. If you need to remove a single item by value and don't care about its return, use remove(). If you need to remove an item by index and don't care about its return, use del. If you need to remove an item by index and want to use it later, use pop().
ConclusionIn this Byte, we've explored the differences between del, remove, and pop in Python. We've seen that del and remove are used for removing items from a list, while pop can also return the removed item. As always, the choice between these methods depends on your specific needs in your code.
Stack Abuse: Subtracting a Day from a Date in Python
Dates are one of the most difficult concepts in programming, largely because of the many different formats that a date can be represented as and the many different nuances of dates (leap years, time zones, etc.). Because of this, date manipulations can be difficult. So what if we need to subtract a day from a date?
This operation is quite common in various domains like data analysis, event scheduling, or even simple things like calculating the previous day's date. In this Byte, we'll explore how to subtract a day from a date using the datetime module and Unix timestamps. We'll also look at other date manipulations, like subtracting more than one day.
Using the datetime ModulePython's datetime module is a powerful tool for dealing with dates and times. To subtract a day from a date, we can use the timedelta object from the datetime module. Here's how:
from datetime import datetime, timedelta # Today's date today = datetime.now() # Subtract a day yesterday = today - timedelta(days=1) print("Today's date:", today) print("Yesterday's date:", yesterday)When you run this script, it will print today's date and the date for the previous day.
Using Unix TimestampsAnother method to subtract a day from a date is by using raw Unix timestamps. A Unix timestamp is a way to track time as a running total of seconds. This count starts at the Unix Epoch on January 1st, 1970. To subtract a day, we subtract 86400 seconds (which is the equivalent of 24 hours) from the current timestamp.
import time # Get the current timestamp now = time.time() # Subtract a day yesterday_timestamp = now - 86400 # Convert the timestamp back to a date yesterday = time.ctime(yesterday_timestamp) print("Current date:", time.ctime(now)) print("Yesterday's date:", yesterday)Again, this code will print the current date and the date for the previous day.
Other Date ManipulationsThere are many other date manipulations you might need to perform apart from subtracting a single day. Let's look at how to subtract more than one day from a date.
Subtracting More Than One DayIf you want to subtract more than one day, you can simply change the value of the days parameter in the timedelta object. For example, to subtract three days from the current date:
from datetime import datetime, timedelta # Today's date today = datetime.now() # Subtract three days three_days_ago = today - timedelta(days=3) print("Today's date:", today) print("Date three days ago:", three_days_ago)This script will print today's date and the date from three days ago. The timedelta object is quite flexible and can be used to subtract any number of days, weeks, or even years from a date.
Subtracting a WeekLet's say you have a date and you want to find out what the date was exactly one week ago. Python's datetime module makes this operation straightforward. Here's an example:
from datetime import datetime, timedelta today = datetime.now() one_week_ago = today - timedelta(weeks=1) print(f"Today's date: {today}") print(f"One week ago: {one_week_ago}")When you run this code, you'll get an output similar to this:
Today's date: 2022-09-30 16:50:21.992728 One week ago: 2022-09-23 16:50:21.992728Note: Remember, the timedelta function allows you to subtract days, seconds, microseconds, milliseconds, minutes, hours, and weeks. It doesn't directly support months or years due to their variable lengths.
Subtracting a MonthSubtracting a month from a date is a bit more involved due to the variability in the number of days in a month. To handle this, we can create a function that checks if subtracting a day would cause the month to change. If so, it will subtract an additional day until it reaches the previous month.
from datetime import datetime, timedelta def subtract_a_month(date): target_month = (date.month - 1) if date.month != 1 else 12 while date.month != target_month: date -= timedelta(days=1) return date today = datetime.now() one_month_ago = subtract_a_month(today) print(f"Today's date: {today}") print(f"One month ago: {one_month_ago}")Running this code might give you an output like this:
Today's date: 2022-09-30 16:50:21.992728 One month ago: 2022-08-30 16:50:21.992728 ConclusionIn this Byte, we've explored a few methods to subtract various time periods from a date using Python, including a week and a month. While Python's datetime and calendar modules are great tools to have, they may not cover every use case. For more complex date manipulations, consider using a library like dateutil.
Stack Abuse: Remove Elements from a List Python by Index
In this Byte we'll be exploring how to remove an element from a list by its index. Whether you're experienced or a novice, you probably find yourself having to do this quite frequently. In the following sections, we'll be showing a couple different methods for removing an element by index.
Python Lists and IndexingPython lists are a type of data structure that can hold an ordered collection of items, which means you can store multiple items in a single variable. These items can be of any type and you can mix types within a single list.
my_list = ["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"] print(my_list) ['apple', 'banana', 'cherry', 'orange', 'kiwi', 'melon', 'mango']In Python, indexing syntax can be used as a substitute for the list.get() method. Python uses zero-based indexing, so the first element has an index of 0.
print(my_list[0]) # prints 'apple' print(my_list[2]) # prints 'cherry' apple cherry How to Remove an Element by IndexThere are several ways to remove an element from a list by its index in Python. The two most common methods are using the pop() method and the del statement. Let's go through each of them.
Using pop() MethodThe pop() method removes the element at the specified position. The method also returns the value of the removed element. This can be useful if you need to use the value after removing it from the list.
my_list = ["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"] removed_element = my_list.pop(1) print(removed_element) # prints 'banana' print(my_list) # prints ['apple', 'cherry', 'orange', 'kiwi', 'melon', 'mango']Output:
banana ['apple', 'cherry', 'orange', 'kiwi', 'melon', 'mango']Note: If you use the pop() method without an index, it removes and returns the last item in the list.
In my experience, I tend to like the pop() method since it's both simple to use and it returns to you the value that was removed.
Using del StatementPython's del statement is a powerful tool that allows you to remove an element from a list by its index. This is a straightforward and efficient way to deal with unwanted elements. Let's see it in action:
fruits = ['apple', 'banana', 'cherry', 'date'] del fruits[1] print(fruits)Output:
['apple', 'cherry', 'date']In this example, we're deleting the second element ('banana') from our list of fruits by referencing its index (1). Remember, Python list indexing starts at 0!
Note: Be careful when using the del statement. If you try to delete an element at an index that doesn't exist, Python will throw an IndexError.
Removing Multiple Elements by IndexWhat if you need to remove multiple elements from a list? You could use the del statement in a loop, but there's a more efficient way. Let's create a function that accepts a list and a set of indices to be removed:
def remove_indices(input_list, indices): indices = set(indices) # remove duplicates input_list = [v for i, v in enumerate(input_list) if i not in indices] return input_list fruits = ['apple', 'banana', 'cherry', 'date'] print(remove_indices(fruits, [0, 2]))Output:
['banana', 'date']In this example, we're removing the first and third elements from our list by passing their indices (0 and 2) to our remove_indices function.
Removing Elements in a RangeIn other scenarios, we may need to remove a range of elements from a list. Python's slice assignment can be used to achieve this. Let's try removing elements from index 1 to 3:
fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry'] fruits[1:3] = [] print(fruits)Output:
['apple', 'date', 'elderberry']Here, 'banana' and 'cherry' have been removed from the list. The slice 1:3 includes indices 1 and 2, but not 3, as Python slice ranges are up to, but not including, the end index.
ConclusionManipulating lists is a fundamental part of programming in Python. Whether you're removing a single element, multiple elements, or a range of elements, Python provides several ways to achieve this.
Robin Wilson: How to get GeoParquet support in GDAL/OGR from conda-forge
Just a quick one this time…
GeoParquet is a cool new-ish format for geospatial data. I’ve tried to use it a couple of times, but always run into issues with my GDAL/OGR install not supporting it. Each time this has led to me giving up, as I couldn’t be bothered to install GDAL from somewhere else.
Today, I found the solution. I usually use GDAL from conda-forge, and it turns out you can install GeoParquet support for that GDAL by just installing an extra conda-forge package:
conda install -c conda-forge libgdal-arrow-parquet(feel free to replace conda with mamba if – like me – you’re using mamba for its speed improvements).
Once this is installed, GeoParquet works in everything that uses that GDAL library – in my case this included the GDAL/OGR command-line tools, plus various Python modules that link to GDAL.
This is actually documented at the end of the GDAL GeoParquet driver page, but I don’t think I’d ever scrolled to the bottom of that before.
Stack Abuse: Limiting Float Decimal Points in Python
In Python, we often deal with numbers that have a fractional part, known as floating-point numbers. But what if we want to limit the number of decimal points in these numbers? This Byte will talk about the concept of floating-point numbers, why we might want to limit their decimal points, and how to do so using Python's built-in functions.
Floating-Point NumbersFloating-point numbers, or simply "floats", are numbers that have a decimal point. In Python, you can define a float by simply including a decimal point in the number, like so:
my_float = 3.14159 print(my_float)Output:
3.14159 Why limit the decimal points?You might be wondering, "Why would I want to limit the decimal points of a float?" Well, there are many reasons. Perhaps you're dealing with a currency value, and you only need two decimal places. Or maybe you're calculating a percentage, and you don't need a high level of precision and want to make it more readable.
Limiting the decimal points can make your data easier to read and understand.
How to Limit a Float's Decimal PointsPython provides several ways to limit the decimal points of a float. We'll cover some of the most common methods here:
Using the round() FunctionThe round() function is a built-in Python function that rounds a number to a specified number of decimal places. By default, it rounds to the nearest whole number, but you can pass a second argument to specify the number of decimal places. Here's how you can use it:
my_float = 3.14159 rounded_float = round(my_float, 2) print(rounded_float)Output:
3.14In this example, we've rounded my_float to two decimal places.
Note: The round() function uses "round half to even" rounding, also known as "bankers' rounding". This means that if the number to be rounded is exactly halfway between two possible values, it will be rounded to the nearest even number. This is something to keep in mind if you're dealing with numbers that often end in .5.
Using the format() FunctionThe format() function is another way to limit a float's decimal points in Python. This formatting method provides more control over how you want your numbers to be displayed.
num = 12.34567 formatted_num = "{:.2f}".format(num) print(formatted_num)Output:
12.35In this example, the :.2f inside the curly braces {} is a format specification for the float number. The .2 part specifies the precision of the numbers after the decimal. The f at the end stands for "fixed point" number, which is used to represent decimal numbers.
Note: The format() function doesn't modify the original float number. Instead, it returns a formatted string. So if you want to use or manipulate this number, you'll need to convert it back into a float.
Using the Decimal ModuleAnother method to limit a float's decimal points is by using the Decimal module in Python. This module provides support for fast correctly rounded decimal floating point arithmetic.
from decimal import Decimal num = Decimal(12.34567) rounded_num = round(num, 2) print(rounded_num)Output:
12.35In this example, we first import the Decimal module. We then convert our float number to a Decimal and use the round() function to limit the decimal points to two.
The Decimal module provides more precision and control over floating point arithmetic than the built-in Python float data type.
Rounding vs Truncating Decimal PointsWhen limiting decimal points, it's important to understand the difference between rounding and truncating. Rounding refers to approximating a number to the nearest value, while truncating means removing the excess digits without rounding.
For instance, if you have the number 12.789 and you want to limit it to two decimal points, rounding would give you 12.79 while truncating would give you 12.78.
Here's how you can truncate a float to two decimal points by using only int and some multiplication/division:
num = 12.789 truncated_num = int(num * 100) / 100 print(truncated_num)Output:
12.78To achieve the truncation, we multiply the float by 100, convert it to an integer to remove the excess decimal points, and then divide it by 100 to get the truncated value.
ConclusionIn this Byte, we explored different ways to limit a float's decimal points in Python using the round(), format(), and Decimal module. We also discussed the difference between rounding and truncating decimal points. The choice of method you use is largely depends on the specific requirements of your program. The Decimal module is a powerful tool for dealing with floating point numbers, especially when precision is most important. However, for simple rounding or formatting, the round() and format() functions are often enough.
Stack Abuse: Capitalizing First Letter of Each Word in Python
Working with strings is a common task in many programming languages. One possible use-case you'll encounter is capitalizing the first letter of each word in a string. This Byte will explore three different ways we can achieve this: using the title(), capitalize(), and string.capwords() functions.
The title() FunctionThe title() function is a built-in method in Python that converts the first character of each word to uppercase and the remaining characters to lowercase. Here's how you can use it:
text = "welcome to stackabuse.com" print(text.title())The output will be:
Welcome To Stackabuse.ComNote: The title() function capitalizes every word in a string, regardless of what the word is. This may not always be the desired behavior. For example, in our output, ".Com" is capitalized, which is not correct in terms of website domain naming conventions. So you may need to handle cases like this manually.
The capitalize() FunctionThe capitalize() function, on the other hand, only capitalizes the first letter of a string, while making all other characters in the string lowercase.
text = "welcome to STACKABUSE.COM" print(text.capitalize())This will output:
Welcome to stackabuse.comAs you can see, only the first letter of the string is capitalized, and all other letters are now lowercase.
The string.capwords() FunctionThe string.capwords() function from the string module is another way to capitalize the first letter of each word in a string. This function splits the string into words using whitespace, capitalizes the first letter of each word, and then joins them back together.
import string text = "welcome to stackabuse.com" print(string.capwords(text))The output will be:
Welcome To Stackabuse.comYou'll notice that in this case, ".com" is not capitalized like we saw with tite(). This is because it only splits on whitespace, so it considers "stackabuse.com" to be one word.
Example: Formatted Output in User InterfacesLet's take a practical example to see how this works. Suppose we're making a user interface for a simple application. We have a form where the user can enter their full name. However, users can be unpredictable and might enter their name in all lower case, all upper case, or a mix of both. To ensure consistency in our application, we want to capitalize the first letter of each word in their name.
Here's how we can achieve this using the title() function:
def format_name(user_input): return user_input.title() user_name = "jane doe" formatted_name = format_name(user_name) print(formatted_name)When we run this script, the output will be:
$ Jane DoeIn this way, no matter how the user enters their name, it will always be formatted correctly in our application.
Although we're using title() in this example, you could also use string.capwords() if you prefer. Both will give you the same result in this case.
Note: While this is a toy example to show when and why you might title words, formatting names isn't actually this easy. There are names out there that don't actually start with a capital letter, like "Ludwig van Beethoven". It would technically incorrect to capitalize the "van". Unfortunately nothing is ever as easy as it seems in programming 😉
ConclusionIn this Byte, we've looked at three different Python functions that can be used to capitalize the first letter of each word in a string: title(), capitalize(), and string.capwords(). Each function has its own unique quirks and use-cases, but all of them can be useful when dealing with text data, depending on your use-case. Whether you're formatting user input in a UI, as in our example, or working with some kind of dataset, these functions can help format your data consistently.
Real Python: The Real Python Podcast – Episode #170: Finding the Right Coding Font for Programming in Python
What should you consider when picking a font for coding in Python? What characters and their respective glyphs should you check before making your decision? This week on the show, we talk with Real Python author and core team member Philipp Acsany about his recent article, Choosing the Best Coding Font for Programming.
[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]
Tryton News: Newsletter September 2023
Please update your systems and take care of a security bug we found last month. See the related announcement.
Soon, in just two months, at the very beginning of November we’ll publish our next Long Term Supported (LTS) release of Tryton, version 7.0. Please test our current released applications in version 6.8 or the actual developments from our repositories.
In the last month we focused on fixing bugs and behaviors, speeding-up performance issues and adding new features for you. We also released bug fixes for the maintained series 5.0, 6.0, 6.6 and 6.8.
All the number fields are now sorted by length. This provides a more natural sorting sequence when the content is just a number or a number with a prefix.
Stock, Sales, Purchase and ProjectOn purchase request we added new domains to filter quoted and received records.
Now Tryton uses the shipping date instead of sale date to check the stock quantities used by the planned quantity and stock forecast.
On purchase and sale we add actions to trigger the creation of draft documents to make the follow-up of the manual invoice and shipment methods easier for the users. As the user may need to manually create those documents anyway, we provide an action that creates those documents as if the method On Order would be used.
In the stock_package* modules we renamed the code field to number.
Accounting, Invoicing and PaymentThe account moves generated from currency exchange values are now automatically posted by the system. This prevents the handling of forgotten unposted currency exchange moves and avoids the need of handling them manually.
A selection widget is now used for the journal field. This prevents the creation of journals directly from documents and makes it simpler to select for the users.
Now Tryton does no longer search for the party when searching for the invoice record name.
User InterfaceThe search offset is now reset when the filter is modified. This improves an unexpected behaviour when the user moved to the second page (updating the offset) and then updates the filter and no records are shown if there are not enough records. With the new behaviour, the first page of the records will be always shown when updating the filter.
It is now possible to copy selected records on the web-client. A new contextual menu has been added to mimic the feature which is available on the desktop client using the keyboard shortcut.
User applications created from the user preferences are now directly in state validated to improve the user experience.
The list of supported identifiers has been increased. The following identifiers have been added:
- Belgian National Number identifier
- Algerian Tax Number identifier
- Faroese Tax Number identifier
- Ghanaian Taxpayer Identification Number identifier
- Indian Voter ID identifier
- Indian VAT number identifier
- Moroccan Tax Number identifier
- Macedonian Tax Number identifier
- Pakistani Computerised National Identity Card Number identifier
- Portuguese Identity Number identifier
- Slovenian Unique Master Citizen Number identifier
- Thai Memorandum of Association Number identifier
- Thai Personal Identification Number identifier
- Thai Taxpayer Identification Number identifier
- Tunisian Tax Number identifier
The new Product Price List Cache Module can be used to pre-compute the prices for each product and price list. This improves the performance of the price list for a big set of lines.
DocumentationOur documentation base improved greatly by a new chapter about the internal resource module.
Changes for the System AdministratorThe account dunning email logs have been merged into the general email archives.
Changes for Implementers and DevelopersThe PostgreSQL backend now supports BTREE_GIN indexing . Also the support for similarity expressions have been improved. Last but not least, the expressions are now filtered.
Now tests can execute the same scenario with a list of different global variables defined in a JSON list.
1 post - 1 participant
The Python Coding Blog: Graduation at Hogwarts and Other Python Stories | August in Review
August is a quiet month, right? Well, not at The Python Coding Stack and Breaking the Rules, my two Substacks.
On The Python Coding Stack, I experimented with some different styles of articles. The month started with The Mayor of Py Town’s Local Experiment: A Global Disaster.
This is Py Town looks like (thanks to Midjourney!) This town was a bit special and its Mayor liked to make a mess of things. The story leads to why variables in function definitions are local variables.
By the way, here’s the Mayor of Py Town.
Another rather different article was Clearing The Deque—Tidying My Daughter’s Soft Toys • A Python Picture Story. This post is a picture story which explains the differences between lists and deques in Python. If a picture is worth a thousand words, then this is the longest article I’ve ever written!
Another post on The Python Coding Stack combined the turtle module with the partial() function and lambda functions to create a typewriter emulator: Tap, Tap, Tap on The Tiny turtle Typewriter.
Another article looked at some Python quirks that can help us understand what happens underneath the hood in Python. This article, Python Quirks? Party Tricks? Peculiarities Revealed, is a paid article but there’s a substantial free preview.
The final two articles this month concluded two long-running series on The Stack
- The final article in the Harry Potter-themed OOP series: The Final Year at Hogwarts School of Codecraft and Algorithmancy (Harry Potter OOP Series #7)
- The final article in the Data Structure Category Series: Pay As You Go • Generate Data Using Generators (Data Structure Categories #7)
And for those interested in my experiments in narrative technical writing, you can read all five articles published in August on Breaking the Rules!
The post Graduation at Hogwarts and Other Python Stories | August in Review appeared first on The Python Coding Book.
Stack Abuse: Differences Between Python's defaultdict and dict
In Python, dictionaries are one of the most flexible built-in data types. They are great for structuring data and can help you solve a myriad of problems. But what if I told you there's a more powerful version of dictionaries that you might not have heard of? Yep, I'm talking about the collections.defaultdict type.
In this article, we'll explore what a defaultdict is and how it differs from a regular Python dictionary (or dict for short).
What is a dict?A dict, or dictionary, is a built-in Python data type that stores mutable, unordered collections of key-value pairs. Each key-value pair in the dictionary maps the key to its associated value, making it easier to retrieve values for specific keys.
student = { "name": "John Doe", "age": 20, "courses": ["Math", "Science"] } print(student["name"]) # Output: John DoeIn this code, the keys are "name", "age", and "courses", and they each have associated values. You can access any value by its key, as we did with student["name"].
But what happens when you try to access a key that doesn't exist in the dictionary? Well, Python throws a KeyError:
print(student["grade"]) # Output: KeyError: 'grade'This is one of the limitations of a normal dictionary. It doesn't handle missing keys very well. In real-world applications, this can cause your program to crash if you're not careful. This is where defaultdicts come into play, but we'll get into that later in the article.
Note: You can avoid KeyError exceptions in normal dictionaries by using the get method, which returns None if the key is not found. However, this isn't always ideal, especially when you want to provide a default value other than None.
print(student.get("grade")) # Output: None What is a defaultdict?A defaultdict is a specialized dictionary provided by the collections module in Python. It's a subclass of the built-in dict class. So, what makes it so special? Well, it doesn't throw a KeyError when you try to access or modify keys that aren't actually in the dictionary. Instead, it initializes it with an element of the data type that you pass as an argument at the creation of defaultdict. This can be very useful when you're working with large data structures.
Let's take a quick look at how you would initialize a defaultdict:
from collections import defaultdict # Initializing with list as default_factory dd = defaultdict(list)In the example above, if you try to access a key that doesn't exist, Python will return an empty list [] instead of throwing a KeyError.
print(dd["non_existent_key"]) # Output: []The argument you pass while initializing defaultdict is called default_factory. It's a function that provides the default value for the dictionary created. If this argument is absent, then the defaultdict essentially behaves like a normal dict.
Key DifferencesNow that we understand what a defaultdict is, let's take a look at the key differences between a defaultdict and a typical Python dictionary.
- Default Values: The most significant difference, as we've already seen, is that defaultdict automatically assigns a default value to a non-existent key. This is in different than a standard dict, which raises a KeyError when you try to access or modify a non-existent key.
- Initialization: While initializing a defaultdict, you need to provide a default_factory function which will decide the default value for the non-existent keys. On the other hand, a standard dict doesn't require or support this.
- Use Cases: defaultdict is more useful when you're dealing with large data sets where you want to avoid handling KeyError exceptions. It's commonly used for grouping, counting, or accumulating operations.
Of course, the choice between defaultdict and dict depends on your specific needs. If you're dealing with a situation where you want to avoid key errors and you know in advance what kind of default value you'd want for non-existing keys, defaultdict is the way to go.
Let's say you're building a dictionary to count the frequency of words in a text. With a normal dictionary, you'd have to check if a word is already a key in the dictionary before incrementing its count. With defaultdict, you can simply set the default value type as int and increment the count without any checks.
On the other hand, if you want your program to throw an error when a non-existent key is accessed, or if you don't have a clear default value, a regular dict may be more suitable.
How to Use defaultdictUsing defaultdict is quite straightforward. You start by importing it from the collections module. Then, when you create a defaultdict, you pass in the default type for the dictionary. This could be int, list, set, dict, or even a user-defined function.
Let's take a look at an example. Suppose we want to create a dictionary to store the grades of students in different subjects. We can use a defaultdict with a list as the default type:
from collections import defaultdict # Create a defaultdict with list as the default type grades = defaultdict(list) # Add grades grades['Math'].append(85) grades['English'].append(90) print(grades)When you run this code, you'll get the following output:
defaultdict(<class 'list'>, {'Math': [85], 'English': [90]})As you can see, we didn't have to check if "Math" or "English" were already keys in the dictionary. We were able to directly append the grades. If we try to access the grades for a subject that hasn't been added yet, we'll get an empty list instead of a key error:
print(grades['Science'])This will output:
[]Note: Remember that the default type you pass to defaultdict is a function, not a value. So, you should pass list instead of [], or int instead of 0.
How to Use dictThe Python dict is a built-in data type used to store data in key-value pairs. Here's a simple example of how to use it:
# Creating a dictionary my_dict = {'name': 'John', 'age': 30} # Accessing a value print(my_dict['name']) # Output: John # Updating a value my_dict['age'] = 31 print(my_dict['age']) # Output: 31 # Adding a new key-value pair my_dict['job'] = 'Engineer' print(my_dict) # Output: {'name': 'John', 'age': 31, 'job': 'Engineer'}One thing to remember when using dict is that it will raise a KeyError if you try to access a key that doesn't exist:
print(my_dict['hobby']) # Raises KeyError: 'hobby'Note: To avoid this, you can use the get() method, which returns None or a default value of your choice if the key doesn't exist.
print(my_dict.get('hobby')) # Output: None print(my_dict.get('hobby', 'default')) # Output: default ConclusionIn this article, we've taken a deeper dive into the world of Python dictionaries, focusing specifically on the dict and collections.defaultdict types. We've explored their key differences, like how defaultdict provides a default value for non-existent keys, thus avoiding KeyError exceptions. We've also looked at their use-cases, with dict being better for scenarios where you need to strictly control what keys exist in your dictionary, and defaultdict being more useful when you're dealing with large datasets and need to avoid constant key existence checks.
PyBites: Empower Your Python Ambitions – From Idea Paralysis to Real-World Projects
In this podcast episode we talk about the significance of building real-world Python applications.
Listen here:
Or watch here:
Bob highlights the importance of breaking away from tutorial paralysis and creating genuine software solutions to understand and confront real-world complexities.
He also emphasizes the career benefits of showcasing tangible Python projects on your portfolio / GitHub / resume.
As an actionable step, listeners are introduced to the Pybites Portfolio Assessment tool.
Through a fictional character, Alex, listeners are guided on how to use the tool identifying their passions, strengths, weaknesses, and ultimately leverage Python to realize their goals through real world app building.
Take the assessment here (your submission will be emailed to Pybites). If you go the manual pen + paper route, then just send it via emial – good luck!
Stack Abuse: Traversing a List in Reverse Order in Python
If you've been coding in Python for a while, you're probably familiar with how to traverse a list in the usual way - from the first element to the last. But what about when you need to traverse a list in reverse order? It might not be something you need to do every day, but when you do, it's good to know how.
In this Byte, we'll explore three different methods to traverse a list in reverse order in Python.
Why Traverse a List in Reverse Order?There are several situations where traversing a list in reverse order can be beneficial. Imagine that you're dealing with a list of events that are stored in chronological order, and you want to process them from most recent to oldest. Or maybe you're implementing an algorithm that requires you to work backwards through a list. Whatever the reason, luckily there are a few ways to accomplish this in Python.
Method 1: Using the reversed() FunctionPython has a built-in function called reversed() that returns a reverse iterator. An iterator is an object that contains a countable number of values and can be iterated (looped) upon. Here's a quick example:
my_list = [1, 2, 3, 4, 5] for i in reversed(my_list): print(i)Output:
5 4 3 2 1The reversed() function doesn't actually modify the original list. Instead, it gives you a reverse iterator that you can loop over. Otherwise, if it were to actually reverse the list and return a new one, this could become a very expensive operation.
Method 2: Using List SlicingAnother way to traverse a list in reverse order is by using list slicing. The slicing operator [:] can take three parameters - start, stop, and step. By setting the step parameter to -1, we can traverse the list in reverse order.
my_list = [1, 2, 3, 4, 5] for i in my_list[::-1]: print(i)Output:
5 4 3 2 1It might not be as readable as using the reverse() method, but it's more compact and is powerful enough to be used in many other use-cases (i.e. traversing every other item from the end).
Method 3: Using a For Loop with range()The third method involves using a for loop with the range() function. The range() function can take three parameters - start, stop, and step. By setting the start parameter to the last index of the list, the stop parameter to -1 (to go all the way to the beginning of the list), and the step parameter to -1 (to go backwards), we can traverse the list in reverse order.
my_list = [1, 2, 3, 4, 5] for i in range(len(my_list) - 1, -1, -1): print(my_list[i])Output:
5 4 3 2 1The range function may have been one of the first ways you learned to generate a list of incrementing numbers, often used for iterating. But you may not have known about the start, stop, and step parameters. Now that you do, you can probably think of other use-cases for this function.
Comparing the MethodsNow that we have seen a few different methods to reverse a list in Python, let's compare them in terms of readability, performance, and use cases.
The reversed() function is the most Pythonic way to reverse a list. It's simple, readable, and efficient. It's especially useful when you need to iterate over the list in reverse order, but don't want to modify the original list.
fruits = ['apple', 'banana', 'cherry'] for fruit in reversed(fruits): print(fruit)Output:
cherry banana appleList slicing is another Pythonic method. It's concise and readable, but it creates a copy of the list, which might not be desirable if you're working with a large list due to memory usage.
fruits = ['apple', 'banana', 'cherry'] print(fruits[::-1])Output:
['cherry', 'banana', 'apple']The for loop with range() is a more traditional approach. It's a bit more verbose and less Pythonic, but it gives you more control over the iteration, such as skipping elements.
fruits = ['apple', 'banana', 'cherry'] for i in range(len(fruits)-1, -1, -1): print(fruits[i])Output:
cherry banana apple Working with Nested ListsReversing a nested list can be a bit tricky. Let's say we have a list of lists and we want to reverse each inner list. Here's how you can do it with list comprehension and the reversed() function.
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] reversed_nested_list = [list(reversed(l)) for l in nested_list] print(reversed_nested_list)Output:
[[3, 2, 1], [6, 5, 4], [9, 8, 7]]You may notice that this did not reverse the order of the inner lists themselves. If you want to do that, you can simply use reversed() again on the outer list.
Traversing in Reverse Order with ConditionsSometimes, you may want to traverse a list in reverse order and perform actions only on certain elements. Let's say we want to print only the odd numbers in reverse order. We can do this using a for loop with range() and an if statement:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9] for i in range(len(numbers)-1, -1, -2): if numbers[i] % 2 != 0: print(numbers[i])Output:
9 7 5 3 1Another way to achieve this with range is to use a step of -2, instead of -1, and to drop the if condition.
ConclusionTraversing a list in reverse order is a common operation in Python, and there are several ways to achieve this. The reversed() function and list slicing are Pythonic methods that are simple and readable, while a for loop with range() gives you more control over the iteration. When working with nested lists or applying conditions, these methods can be combined and adapted to fit your needs.
Zero to Mastery: Python Monthly Newsletter 💻🐍
Stack Abuse: Python Naming Conventions for Variables, Functions, and Classes
Python, like any other programming language, has its own set of rules and conventions when it comes to naming variables and functions. These conventions aren't just for aesthetics or to make your code look pretty, they serve a much more important role in making your code more readable and maintainable. If you've read many of my articles on StackAbuse, I talk a lot about writing readable code. By following Pythonic best-practices in naming and formatting your code, you'll make it much more readable for others (and yourself).
In this article, we'll explore the different naming conventions used in Python and understand why they matter.
Why Naming Conventions MatterImagine working on a large codebase where variables and functions are named/formatted haphazardly. It would be a nightmare to understand what each variable or function does, let alone debug or add new features. This is one of the reasons why we put so much emphasis on following conventions.
Naming conventions are basically just agreed-upon standards that programmers follow when naming their variables, functions, classes, and other code elements. They provide a level of predictability that makes it easier to understand the purpose of a piece of code. This is especially important when you're working in a team.
Following naming conventions isn't just about making your code understandable to others. It's also about making it easier for your future self. You might understand your code perfectly well now, but you might not remember what everything does six months down the line.
Variable Naming ConventionsIn Python, variable names are more than just placeholders for values - they are a vital part of your code's readability. Python's variable naming convention is based on the principle of "readability counts", one of the guiding philosophies of Python.
A variable name in Python should be descriptive and concise, making it easy for anyone reading your code to understand what the variable is used for. It should start with a lowercase letter, and it can include letters, numbers, and underscores. However, it cannot start with a number.
Here are some examples:
name = "John Doe" age = 30 is_student = FalseNote: Python is case sensitive, which means age, Age, and AGE are three different variables.
In Python, we commonly use snake_case for variable names, where each word is separated by an underscore. This is also known as lower_case_with_underscores.
student_name = "John Doe" student_age = 30 is_student = False Function Naming ConventionsLike variable names, function names in Python should be descriptive and concise. The function name should clearly indicate what the function does. Python's naming conventions for functions are similar to its conventions for variables.
In Python, we typically use snake_case for function names. Here's an example:
def calculate_sum(a, b): return a + b result = calculate_sum(5, 3) print(result) # Output: 8Note: It's a good practice to use verbs in function names since a function typically performs an action.
In addition to snake_case, Python also uses PascalCase for naming classes, and occassionally camelCase, but we'll focus on those in another section. For now, remember that consistency in your naming convention is important for to writing clean, Pythonic code.
Class Naming ConventionsFor naming classes in Python, a different set of conventions applies compared to naming variables or functions. In Python, class names typically use PascalCase, also known as UpperCamelCase. This means that the name starts with an uppercase letter and has no underscores between words. Each word in the name should also start with an uppercase letter.
Here's an example to illustrate the naming convention for classes:
class ShoppingCart: def __init__(self, items=[]): self.items = items def add_item(self, item): self.items.append(item) my_cart = ShoppingCart() my_cart.add_item("apple")In this example, ShoppingCart is a class that adheres to the PascalCase naming convention.
Note: While function names often use verbs to indicate actions, class names usually employ nouns or noun phrases. This is because a class often represents a thing or a concept rather than an action.
Sometimes you'll encounter classes that contain acronyms or initialisms. In such cases, it's conventional to keep the entire acronym uppercase:
class HTTPResponse: def __init__(self, status_code, content): self.status_code = status_code self.content = contentJust like with functions, the key to good class naming is to be descriptive and concise. The name should clearly convey the class's purpose or functionality. And as always, maintaining consistency in your naming conventions throughout your codebase is vital for readability and maintainability.
ConclusionIn this article, we've explored the importance of naming conventions in Python, and how they contribute to code readability and maintainability. We've showed the different types of naming conventions for variables, functions, and classes, like PascalCasing and snake_casing.
Python does not enforce these conventions, but adhering to them is considered good practice and can really improve your code's readability, especially when working in teams.
Mike Driscoll: Textual Apps Coming to a Website Near You
Textual is an amazing Python package for creating Text-Based User Interfaces (TUIs) in Python. You can learn more in An Intro to Textual – Creating Text User Interfaces with Python.
However, Textual isn’t only about creating user interfaces for your terminal. The Textual team is also making Textual for the web! Textual Cloud Service will allow developers to run their terminal GUIs in web applications.
When creating a Textual-based web application, you will use a Textual Agent. These agents can be configured to serve single or multiple textual apps using a TCP/IP connection to a cloud service that supports the Websocket protocol.
According to the Textual Cloud Service documentation, the benefits of using their service are as follows:
- Works over proxies – The websocket protocol is designed to cooperate with network infrastructure such as proxies.
- Bypasses firewalls – Firewalls are generally configured to allow outgoing TCP/IP connections.
- Encrypted – Connections are encrypted with industry standards.
- Compressed – Data is compressed on the fly.
Keep an eye on the Textual product so you know when this new feature goes live!
Related Reading- Python Based Textual Apps Are Coming to the Web – InfoWorld.
- An Intro to Textual – Creating Text User Interfaces with Python
The post Textual Apps Coming to a Website Near You appeared first on Mouse Vs Python.
Stack Abuse: Creating a Dictionary with Comprehension in Python
As you've probably come to learn with Python, there are quite a few ways to do an operation, some methods being better than others. One of the features that contribute to its power is the ability to create dictionaries using dictionary comprehension. This Byte will introduce you to this concept and demonstrate how it can make your code more efficient and readable.
Why Use Dictionary Comprehension?Dictionary comprehension is a concise and memory-efficient way to create and populate dictionaries in Python. It follows the principle of "Do more with less code". It's not just about writing less code, it's also about making the code more readable and easier to understand.
Consider a scenario where you need to create a dictionary from a list. Without dictionary comprehension, you would need to create an empty dictionary and then use a for loop to add elements to it. With dictionary comprehension, you can do this in a single line of code, as we'll see later.
Intro to List ComprehensionBefore we dive into dictionary comprehension, let's first understand list comprehension. List comprehension is a syntactic construct available in Python for creating a list from existing lists. It follows the form of the mathematical set-builder notation (set comprehension).
Here's an example:
# Without list comprehension numbers = [1, 2, 3, 4, 5] squares = [] for n in numbers: squares.append(n**2) print(squares) # [1, 4, 9, 16, 25] # With list comprehension numbers = [1, 2, 3, 4, 5] squares = [n**2 for n in numbers] print(squares) # [1, 4, 9, 16, 25]As you can see, list comprehension allows you to create lists in a very concise way.
Link: For a deeper dive into list comprehension, check out our guide, List Comprehensions in Python.
Converting List Comprehension to Dictionary ComprehensionNow that you understand list comprehension, converting it to dictionary comprehension is pretty straightforward. The main difference is that while list comprehension outputs a list, dictionary comprehension outputs a dictionary, obviously 😉.
To convert a list comprehension to a dictionary comprehension, you need to change the brackets [] to braces {}, and add a key before the colon :.
Let's see what this would look like:
# List comprehension numbers = [1, 2, 3, 4, 5] squares = [n**2 for n in numbers] print(squares) # [1, 4, 9, 16, 25] # Dictionary comprehension numbers = [1, 2, 3, 4, 5] squares = {n: n**2 for n in numbers} print(squares) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}In the dictionary comprehension, n is the key and n**2 is the value. The comprehension iterates over the numbers list, assigns each number to n, and then adds n as a key and n**2 as a value to the squares dictionary.
Simple Examples of Dictionary ComprehensionDictionary comprehension in Python is an efficient way to create dictionaries. It's a concise syntax that reduces the amount of code you need to write. Let's start with a simple example.
# Creating a dictionary of squares for numbers from 0 to 5 squares = {num: num**2 for num in range(6)} print(squares)Output:
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}In this example, the expression num: num**2 is the key-value pair of the new dictionary. The for num in range(6) is the context of the dictionary comprehension, specifying the range of numbers to include in the dictionary.
Advanced Dictionary ComprehensionYou can also use dictionary comprehension for more complex operations. Let's take a look at a case where we create a dictionary from a list of words, with the words as keys and their lengths as values.
words = ["Python", "comprehension", "dictionary", "example"] word_lengths = {word: len(word) for word in words} print(word_lengths)Output:
{'Python': 6, 'comprehension': 13, 'dictionary': 10, 'example': 7}The expression word: len(word) generates the key-value pairs. The for word in words provides the context, iterating over each word in the list.
ConclusionDictionary comprehension in Python offers a concise and efficient way to create dictionaries. By understanding how to use it properly, you can write cleaner, more efficient code. As with any tool, the key to using this effectively is understanding its strengths and limitations.
Real Python: Get Started With Django: Build a Portfolio App
Django is a fully featured Python web framework that you can use to build complex web applications. In this tutorial, you’ll jump in and learn Django by completing an example project. You’ll follow the steps to create a fully functioning web application and, along the way, learn what some of the most important features of the framework are and how they work together.
In this tutorial, you’ll:
- Learn about the advantages of using Django
- Investigate the architecture of a Django site
- Set up a new Django project with multiple apps
- Build models and views
- Create and connect Django templates
- Upload images into your Django site
At the end of this tutorial, you’ll have a working portfolio website to showcase your projects. If you’re curious about how the final source code looks, then you can click the link below:
Get Your Code: Click here to download the Python source code for your Django portfolio project.
Learn DjangoThere are endless web development frameworks out there, so why should you learn Django over any of the others? First of all, it’s written in Python, one of the most readable and beginner-friendly programming languages out there.
Note: This tutorial assumes an intermediate knowledge of the Python language. If you’re new to programming with Python, then check out the Python Basics learning path or the introductory course.
The second reason you should learn Django is the scope of its features. When building a website, you don’t need to rely on any external libraries or packages if you choose Django. This means that you don’t need to learn how to use anything else, and the syntax is seamless because you’re using only one framework.
There’s also the added benefit that Django is straightforward to update, since the core functionality is in one package. If you do find yourself needing to add extra features, there are several external libraries that you can use to enhance your site.
One of the great things about the Django framework is its in-depth documentation. It has detailed documentation on every aspect of Django and also has great examples and even a tutorial to get you started.
There’s also a fantastic community of Django developers, so if you get stuck, there’s almost always a way forward by either checking the docs or asking the community.
Django is a high-level web application framework with loads of features. It’s great for anyone new to web development due to its fantastic documentation, and it’s especially great if you’re also familiar with Python.
Understand the Structure of a Django WebsiteA Django website consists of a single project that’s split into separate apps. The idea is that each app handles a self-contained task that the site needs to perform. As an example, imagine an application like Instagram. There are several different tasks that it needs to perform:
- User management: Logging in and out, registering, and so on
- The image feed: Uploading, editing, and displaying images
- Private messaging: Sending messages between users and providing notifications
These are each separate pieces of functionality, so if this example were a Django site, then each piece of functionality would be a different Django app inside a single Django project.
Note: A Django project contains at least one app. But even when there are more apps in the Django project, you commonly refer to a Django project as a web app.
The Django project holds some configurations that apply to the project as a whole, such as project settings, URLs, shared templates and static files. Each application can have its own database, and it’ll have its own functions to control how it displays data to the user in HTML templates.
Each application also has its own URLs as well as its own HTML templates and static files, such as JavaScript and CSS.
Django apps are structured so that there’s a separation of logic. It supports the model-view-controller pattern, which is the architecture for most web frameworks. The basic principle is that each application includes three separate files that handle the three main pieces of logic separately:
- Model defines the data structure. This is usually the database description and often the base layer to an application.
- View displays some or all of the data to the user with HTML and CSS.
- Controller handles how the database and the view interact.
If you want to learn more about the MVC pattern, then check out Model-View-Controller (MVC) Explained – With Legos.
In Django, the architecture is slightly different. Although it’s based on the MVC pattern, Django handles the controller part itself. There’s no need to define how the database and views interact. It’s all done for you!
The pattern Django utilizes is called the model-view-template (MVT) pattern. All you need to do is add some URL configurations that the views map to, and Django handles the rest!
Read the full article at https://realpython.com/get-started-with-django-1/ »[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]
Mike Driscoll: An Intro to Protocol Buffers with Python
Protocol buffers are a data serialization format that is language agnostic. They are analogous to Python’s own pickle format, but one of the advantages of protocol buffers is that they can be used by multiple programming languages.
For example, Protocol buffers are supported in C++, C#, Dart, Go, Java, Kotlin, Objective-C, PHP, Ruby, and more in addition to Python. The biggest con for Protocol buffers is that far too often, the versions have changes that are not backward compatible.
In this article, you will learn how to do the following:
- Creating a Protocol format
- Compiling Your Protocol Buffers File
- Writing Messages
- Reading Messages
Let’s get started!
Creating a Protocol FormatYou’ll need your own file to create your application using protocol buffers. For this project, you will create a way to store music albums using the Protocol Buffer format.
Create a new file named music.proto and enter the following into the file:
syntax = "proto2"; package music; message Music { optional string artist_name = 1; optional string album = 2; optional int32 year = 3; optional string genre = 4; } message Library { repeated Music albums = 1; }The first line in this code is your package syntax, “proto2”. Next is your package declaration, which is used to prevent name collisions.
The rest of the code is made up of message definitions. These are groups of typed fields. There are quite a few differing types that you may use, including bool, int32, float, double, and string.
You can set the fields to optional, repeated, or required. According to the documentation, you rarely want to use required because there’s no way to unset that. In fact, in proto3, required is no longer supported.
Compiling Your Protocol Buffers FileTo be able to use your Protocol Buffer in Python, you will need to compile it using a program called protoc. You can get it here. Be sure to follow the instructions in the README file to get it installed successfully.
Now run protoc against your proto file, like this:
protoc --python_out=. .\music.proto --proto_path=.The command above will convert your proto file to Python code in your current working directory. This new file is named music_pb2.py.
Here are the contents of that file:
# -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # source: music.proto """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import symbol_database as _symbol_database from google.protobuf.internal import builder as _builder # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bmusic.proto\x12\x05music\"H\n\x05Music\x12\x13\n\x0b\x61rtist_name\x18\x01 \x01(\t\x12\r\n\x05\x61lbum\x18\x02 \x01(\t\x12\x0c\n\x04year\x18\x03 \x01(\x05\x12\r\n\x05genre\x18\x04 \x01(\t\"\'\n\x07Library\x12\x1c\n\x06\x61lbums\x18\x01 \x03(\x0b\x32\x0c.music.Music') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'music_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None _globals['_MUSIC']._serialized_start=22 _globals['_MUSIC']._serialized_end=94 _globals['_LIBRARY']._serialized_start=96 _globals['_LIBRARY']._serialized_end=135 # @@protoc_insertion_point(module_scope)There’s a lot of magic here that uses descriptors to generate classes for you. Don’t worry about how it works; the documentation doesn’t explain it well either.
Now that your Protocol Buffer is transformed into Python code, you can start serializing data!
Writing MessagesTo start serializing your data with Protocol Buffers, you must create a new Python file.
Name your file music_writer.py and enter the following code:
from pathlib import Path import music_pb2 def overwrite(path): write_or_append = "a" while True: answer = input(f"Do you want to overwrite '{path}' (Y/N) ?").lower() if answer not in "yn": print("Y or N are the only valid answers") continue write_or_append = "w" if answer == "y" else "a" break return write_or_append def music_data(path): p = Path(path) write_or_append = "w" if p.exists(): write_or_append = overwrite(path) library = music_pb2.Library() new_music = library.albums.add() while True: print("Let's add some music!\n") new_music.artist_name = input("What is the artist name? ") new_music.album = input("What is the name of the album? ") new_music.year = int(input("Which year did the album come out? ")) more = input("Do you want to add more music? (Y/N)").lower() if more == "n": break with open(p, f"{write_or_append}b") as f: f.write(library.SerializeToString()) print(f"Music library written to {p.resolve()}") if __name__ == "__main__": music_data("music.pro")The meat of this program is in your music_data() function. Here you check if the user wants to overwrite their music file or append to it. Then, you create a Library object and prompt the user for the data they want to serialize.
For this example, you ask the user to enter an artist’s name, album, and year. You omit the genre for now, but you can add that yourself if you’d like to.
After they enter the year of the album, you ask the user if they would like to add another album. The application will write the data to disk and end if they don’t want to continue adding music.
Here is an example writing session:
Let's add some music! What is the artist name? Zahna What is the name of the album? Stronger Than Death Which year did the album come out? 2023 Do you want to add more music? (Y/N)Y Let's add some music! What is the artist name? KB What is the name of the album? His Glory Alone II Which year did the album come out? 2023 Do you want to add more music? (Y/N)NNow, let’s learn how to read your data!
Reading MessagesNow that you have your Protocol Buffer Messages written to disk, you need a way to read them.
Create a new file named music_reader.py and enter the following code:
from pathlib import Path import music_pb2 def list_music(music): for album in music.albums: print(f"Artist: {album.artist_name}") print(f"Album: {album.album}") print(f"Year: {album.year}") print() def main(path): p = Path(path) library = music_pb2.Library() with open(p.resolve(), "rb") as f: library.ParseFromString(f.read()) list_music(library) if __name__ == "__main__": main("music.pro")This code is a little simpler than the writing code was. Once again, you create an instance of the Library class. This time, you loop over the library albums and print out all the data in the file.
If you had added the music in this tutorial to your Protocol Buffers file, when you run your reader, the output would look like this:
Artist: Zahna Album: Stronger Than Death Year: 2023 Artist: KB Album: His Glory Alone II Year: 2023Give it a try with your custom music file!
Wrapping UpNow you know the basics of working with Protocol Buffers using Python. Specifically, you learned about the following:
- Creating a Protocol format
- Compiling Your Protocol Buffers File
- Writing Messages
- Reading Messages
Now is your chance to consider using this type of data serialization in your application. Once you have a plan, give it a try! Protocol buffers are a great way to create data in a programming language-agnostic way.
Further ReadingThe post An Intro to Protocol Buffers with Python appeared first on Mouse Vs Python.