Basics of Exception Handling in Python #2

Of course, we can also use the syntax in which the exception description is assigned to a variable and we can then display it in the handling procedure, e.g.

except NameError as e:
    print('Message:', e)

You can create a common handler for several exceptions by putting class names in a tuple, e.g.

except (ZeroDivisionError, NameError):
    # Here we put the handler for these two exceptions

What you should pay attention to is that exceptions that are child classes in the hierarchy of exception classes are handled before the classes from which they inherit. The wrong order will result in the exception being handled by the more general procedure that came first, i.e.

except Exception:
    print('It catches all exceptions!')
except NameError:
    print('NameError exception')

In the above example, NameError will be handled by the procedure in the first except block. Despite the NameError exception, the following message will be displayed: It catches all exceptions! and the routine that specifically handles this exception (and displays NameError exception in this case) will not be executed.

>>part three<<

Basics of Exception Handling in Python #1

Errors that show up during the execution of the program and are not syntax errors belong to the so-called exceptions. The list of exceptions is quite extensive >>see<<

We can handle these exceptions by putting code that can cause an exception in a try block, i.e.

ry:
    # Here we put code that can raise an exception or exceptions

and the code to handle the exception in the except block (equivalent to Java catch), i.e.

except:
    # Here we put the exception handling code

It is more useful to react to specific exceptions than to handle all of them “in bulk”. The except statement itself without specifying the name of the error class can be useful if you want to catch an exception that has not yet been handled by an earlier except block, e.g.

except ZeroDivisionError:
    # Here we put the code to handle the ZeroDivisionError exception

except NameError:
    # Here we put the code to handle the NameError exception

except:
    # Here we catch the remaining unhandled exceptions

>>part 2<<

Simple calendar display tool


This program is a simple equivalent of the console tool cal, which displays a calendar for a given year and month in the console.

If no arguments are given, it prints the calendar for the current year and month by default. /screenshot/

#!/usr/bin/env python

from datetime import datetime

from calendar import monthrange, weekheader, weekday

from sys import stdout


def cal(year=datetime.today().year, month=datetime.today().month):
    """
    Prints month calendar for given year and month.
    """

    this_year = year
    this_month = month

    # number of all days in month
    days_in_month = monthrange(this_year, this_month)[1]

    # which week day is the first day of month
    first_day_of_month = weekday(this_year, this_month, 1)

    # prints header of calendar (width 5)
    print(weekheader(5))

    # positioning loop
    # for proper position of the first element
    for i in range(first_day_of_month):
        stdout.write(6 * ' ')

    i = 1
    while i <= days_in_month:
        stdout.write(' {:>2}   '.format(i))
        # new line if sunday
        if weekday(this_year, this_month, i) == 6:
            print('')
        i += 1
    print('')

if __name__ == '__main__':
    cal()

Date picker for tkinter

It is a utility class for the project described in this post. You can use it freely in your project (MIT license). Project files you can find here.

My date picker class code:

import tkinter as tk
import calendar
from datetime import datetime
from functools import partial


class DatePicker():
    def __init__(self, root, date_entry, date_strf):
        self.root = root
        self.date_entry = date_entry
        self.date_strf = date_strf
        self.top_level = tk.Toplevel(self.root)
        self.top_level.grab_set()
        self.top_level.title('Date picker')
        x = self.root.winfo_rootx()
        y = self.root.winfo_rooty()
        width = self.root.winfo_width()
        height = self.root.winfo_height()
        self.top_level.geometry(
            '+{}+{}'.format(x + int(width / 2), y + int(height / 2)))

As you can see I’ve created child window in function __init__() as an instance of class tk.Toplevel. Then I blocked widgets in the parent window until date picker window closes (grab_set() function). The next lines describe the position of date picker window relative to the parent window.

        self.c = calendar
        self.cal = self.c.Calendar(self.c.firstweekday())
        self.dp_frame = None
        self.create_cal_ui()

Than I’ve made an instance of Calendar class. Nex, dp_frame variable which stores an instance of tk.Frame class was set up. Then the method create_cal_ui() arranges widgets in window.

create_cal_ui() method:

    def create_cal_ui(self, year=datetime.today().year, month=datetime.today().month):

        mc = self.cal.monthdayscalendar(year, month)
        self.month = month
        self.year = year
        month_txt = self.c.month_name[month]
        self.date_str = f'{month_txt} {year}'

        if self.dp_frame is not None:
            self.dp_frame.destroy()

        self.dp_frame = tk. Frame(self.top_level)
        self.dp_frame.grid(column=0, row=0)

        self.prev_img = tk.PhotoImage(file='Resources/prev.gif')
        self.next_img = tk.PhotoImage(file='Resources/next.gif')
        prev_btn = tk.Button(self.dp_frame, image=self.prev_img, relief='flat')
        prev_btn.bind(
            '<Button-1>', lambda event: self.set_date(event, 'prev_btn'))
        prev_btn.grid(row=0, column=0)
        next_btn = tk.Button(self.dp_frame, image=self.next_img, relief='flat')
        next_btn.bind(
            '<Button-1>', lambda event: self.set_date(event, 'next_btn'))
        next_btn.grid(row=0, column=6)
        self.date_lbl = tk.Label(self.dp_frame, text=self.date_str,
                                 font=12)
        self.date_lbl.grid(row=0, column=1, columnspan=5, sticky='WE')

        week_names = self.c.day_abbr
        for i, name in enumerate(week_names):
            label = tk.Label(self.dp_frame, text=name).grid(column=i, row=1)

        col = 0
        row = 2
        for week in mc:
            for day in week:
                state = 'normal'
                if day == 0:
                    state = 'disabled'
                    day = ''
                day = str(day)
                button = tk.Button(self.dp_frame, text=day,
                                   relief='flat', state=state, command=partial(self.get_date, day))
                button.grid(column=col, row=row)
                col += 1
            row += 1
            col = 0

Method create_cal_ui() takes year and month as arguments – default: current year and current month. Then monthdayscalendar() function from Calendar class gets the list of days in month. Each week is a separate list, so you have a list of lists. Days not belonging to the current month are marked as 0 (zero). The month_txt represents the month string and self.month holds integer value of a month.

 if self.dp_frame is not None:
            self.dp_frame.destroy()

It checks if month is changed. If so, the current frame is destroyed.

Then I create prev_btn and next_btn buttons to change month and date_lbl label to show selected month. In order to change a month I had to bind a method to a button. Event argument does’t have a sender name information. So I’ve created lambda function to pass additional string argument to set_date() method.

prev_btn.bind(
            '<Button-1>', lambda event: self.set_date(event, 'prev_btn'))
next_btn.bind(
            '<Button-1>', lambda event: self.set_date(event, 'next_btn'))

Next I put week names abbreviations:

    week_names = self.c.day_abbr
    for i, name in enumerate(week_names):
        label = tk.Label(self.dp_frame, text=name).grid(column=i, row=1)

Then the day buttons are shown. When pressed on a button get_date() method runs. I used partial function from functools module. Lambda function doesn’t work in this case due to late binding.

col = 0
        row = 2
        for week in mc:
            for day in week:
                state = 'normal'
                if day == 0:
                    state = 'disabled'
                    day = ''
                day = str(day)
                button = tk.Button(self.dp_frame, text=day,
                                   relief='flat', state=state, command=partial(self.get_date, day))
                button.grid(column=col, row=row)
                col += 1
            row += 1
            col = 0

Code of set_date() method:

    def set_date(self, event, sender):
        if sender == 'prev_btn':
            self.month -= 1
            if self.month < 1:
                self.month = 12
                self.year -= 1
        if sender == 'next_btn':
            self.month += 1
            if self.month > 12:
                self.month = 1
                self.year += 1
        self.create_cal_ui(self.year, self.month)

Code of get_date() method:

def get_date(self, day):
    day = int(day)
    self.date_entry.delete(0, tk.END)
    d = datetime(self.year, self.month, day)
    self.date_entry.insert(0, d.strftime(self.date_strf))
    self.top_level.destroy()

I’ve made datetime object instance with formatting. Then I’ve cleared date_entry and added new content. Finally when date is chosen the date picker is destroyed.