Python Workshop: Part 2

Slashdot it! Delicious Share on Facebook Tweet! Digg!

The Source Code…

The source code for your GUI program is in Listing 2, and I'll describe it later line by line.

Listing 2

recursive_gui.py

01 #!/usr/bin/env python
02 # -*- coding: utf-8 -*-
03
04 """GUI for recursive calculation of the size of
05    all files in a directory tree.
06 """
07
08 import sys
09 from PySide import QtGui
10 from recursive_func import get_total_size
11
12 class Form(QtGui.QDialog):
13   """Main Window.
14   """
15   def __init__(self, parent=None):
16     super(Form, self).__init__(parent)
17     self.setWindowTitle(u"Recurser")
18     self.path = QtGui.QLineEdit(u"<textentry>")
19     self.button = QtGui.QPushButton(u"Calculate Size")
20     self.res = QtGui.QLabel(u"Result")
21     layout = QtGui.QVBoxLayout()
22     layout.addWidget(self.path)
23     layout.addWidget(self.button)
24     layout.addWidget(self.res)
25     self.setLayout(layout)
26     self.button.clicked.connect(self.calculate)
27
28   def calculate(self):
29     """Display the calculated result.
30     """
31     path = self.path.text()
32     self.res.setText(u'Total: %d' % get_total_size(path))
33
34 def show_app():
35   """Display the window.
36   """
37   app = QtGui.QApplication(sys.argv)
38   form = Form()
39   form.show()
40   sys.exit(app.exec_())
41
42 if __name__ == '__main__':
43   show_app()

Download the Python script from the Internet [1] and make it executable with:

chmod +x recursive_gui.py

If you enter the code yourself, be sure to save the file with UTF-8 encoding. Then, call the script using ./recursive_gui.py to get the results in Figure 1. As in the previous workshop, the program adds up all the file sizes in a specified directory and all its subdirectories. In the text field, enter the name of the directory and click the Calculate Size button (Figure 2).

Figure 1: The GUI developed with the PySide toolkit is platform-independent and awaits user entry.
Figure 2: Enter the directory name and click "Calculate Size" to get the total file sizes.

Step by Step

Next, I'll look at this Python program in detail. Line 01 with #!/usr/bin/env python points to the command python . The #! is pronounced shebang and works on all Unix-like systems. The system knows right away which language is in use and where to find the matching interpreter.

After the obligatory doc string, starting at line 08, you import several modules. The module sys is from the standard library; you usually list this module first. Next, you import the module QtGui from the PySide package that provides all functions needed for the GUI application. Finally, you import the recursive_func module that you used in the last workshop that's in the download archive and whose get_total_size() function you're already familiar with.

Even though recursive_func is short, you should resist any temptation of defining the get_total_size() function inside the module with the GUI. It's good practice to separate the source code for the graphical interface as much as possible from the other program functions. Distributing it among different files, as shown here, can help in that respect. That way you can apply a command-line interface without much trouble or use the get_total_size() function in another program.

The class Form(QtGui.QDialog): section starting at line 12 defines the new form class that inherits the methods and attributes from QtGui.QDialog (the QDialog class from the QtGui module). Thus the class Form can get everything from QDialog , and that's quite a bit, as Listing 3 shows. The dir() command in the listing creates a list with all the names of the attribute belonging to the class, and len() determines how long the list is: There are 348 attributes.

Listing 3

Attributes of QDialog

>>> from PySide import QtGui
>>> len(dir(QtGui.QDialog))
348
>>> print dir(QtGui.QDialog)
<long list of names>

The next step is to construct the graphical interface (Figure 3). That all happens in the indented code after def __init__(self, parent=None): on line 15. Python always executes the __init__() method when you create an instance of a class. That happens on line 38 with form = Form and you get the new instance form of the class Form . This makes Python execute all the steps in the __init__ method on line 15.

Figure 3: The form class defines the elements that appear in the graphical user interface.

The expression super(Form, self).__init__(parent) on line 16 is necessary so that Python correctly initializes the QtGui.QDialog class. On lines 17 through 20, PySide creates the different graphical elements step by step. After setting the name of the window with setWindowTitle() , the method adds three GUI elements: a text entry field with QLineEdit() , a button with QPushButton() , and the results label with QLabel() . The u before text such as in u"Result" indicates Unicode text so that you can use special language characters.

From line 21, the program puts the three GUI elements into the so-called QVBoxLayout() container that organizes the elements vertically in the layout (Figure 3). You first create an instance of the container and add the elements with layout.addWidget() . The code on line 25 self.setLayout() puts the container in the empty program window.

Once you've defined the graphical elements, make sure that something happens when the user clicks the Calculate Size button. In this case, Python should call the calculate() method. This is specified on line 26 with self.button.clicked.connect(self.calculate) .

With self.path.text() on line 31, calculate gets the text from the entry field. This text must be a valid pathname. The function get_total_size() on line 32 uses the pathname as argument, calculates the file sizes, and delivers the result to the method self.res.setText() , which renders the result in the graphical interface.

At this point, you've defined all essential functions and classes, but you still have to start the application. The show_app() function on the last line does that for you. First, it creates an instance of a QApplication and then an instance of the class Form . The call to form.show() on line 39 puts the application on the screen.

In the next line, sys.exit() calls the Qt application using (app.exec_() ). The function sys.exit() allows to give the calling application an exit status when the program finishes. A status code of 0 indicates success while other codes indicate particular errors. The box "Exit Status in PySide" provides more details.

Exit Status in PySide

PySide is a Python wrapper around Qt, which is written in C++. Qt returns codes for the exit status as numbers. Each number other than zero stands for a particular error. The calling application can use the returned error after the GUI program terminates to do something useful. For this case, the error will go to the terminal window where you typed the command to start your program. You can retrieve the last exit status with echo $? . It should be zero if everything went as expected.

Infos

  1. Source code: ftp://ftp.linux-magazin.de/pub/listings/ubuntu-user.com/
  2. "Python Workshop" by Mike Mueller, Ubuntu User , Issue 15, pg. 50
  3. PySide: http://www.pyside.org
  4. Python Academy: http://www.python-academy.com

The Author

Mike Müeller is the managing director of the Python Academy [4] and an experienced Python trainer. Since he discovered Python in 1999, it has become his favorite programming language. He is a regular speaker at national and international Python conferences and has introduced many students to the advantages of Python.

Buy this article as PDF

Express-Checkout as PDF

Pages: 4

Price $0.99
(incl. VAT)

Buy Ubuntu User

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content