0% found this document useful (0 votes)
83 views

Download Advanced Guide to Python 3 Programming Hunt ebook All Chapters PDF

Hunt

Uploaded by

porthyembi
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
83 views

Download Advanced Guide to Python 3 Programming Hunt ebook All Chapters PDF

Hunt

Uploaded by

porthyembi
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 55

Experience Seamless Full Ebook Downloads for Every Genre at textbookfull.

com

Advanced Guide to Python 3 Programming Hunt

https://textbookfull.com/product/advanced-guide-to-
python-3-programming-hunt/

OR CLICK BUTTON

DOWNLOAD NOW

Explore and download more ebook at https://textbookfull.com


Recommended digital products (PDF, EPUB, MOBI) that
you can download immediately if you are interested.

Python Advanced Programming: The guide to learn pyhton


programming Marcus Richards

https://textbookfull.com/product/python-advanced-programming-the-
guide-to-learn-pyhton-programming-marcus-richards/

textboxfull.com

Learn to Program with Python 3: A Step-by-Step Guide to


Programming Irv Kalb

https://textbookfull.com/product/learn-to-program-with-
python-3-a-step-by-step-guide-to-programming-irv-kalb/

textboxfull.com

Learn to Program with Python 3: A Step-by-Step Guide to


Programming, 2nd Edition Irv Kalb

https://textbookfull.com/product/learn-to-program-with-
python-3-a-step-by-step-guide-to-programming-2nd-edition-irv-kalb/

textboxfull.com

A Beginner’s Guide to Scala, Object Orientation and


Functional Programming John Hunt

https://textbookfull.com/product/a-beginners-guide-to-scala-object-
orientation-and-functional-programming-john-hunt/

textboxfull.com
A Beginner's Guide to Scala, Object Orientation and
Functional Programming (Second Edition) John Hunt

https://textbookfull.com/product/a-beginners-guide-to-scala-object-
orientation-and-functional-programming-second-edition-john-hunt/

textboxfull.com

Practical Programming An Introduction to Computer Science


Using Python 3 6 3rd Edition Paul Gries

https://textbookfull.com/product/practical-programming-an-
introduction-to-computer-science-using-python-3-6-3rd-edition-paul-
gries/
textboxfull.com

Python 3 Object Oriented Programming 3rd Edition Dusty


Phillips [Dusty Phillips]

https://textbookfull.com/product/python-3-object-oriented-
programming-3rd-edition-dusty-phillips-dusty-phillips/

textboxfull.com

Python Basics A Practical Introduction to Python 3


Fletcher Heisler

https://textbookfull.com/product/python-basics-a-practical-
introduction-to-python-3-fletcher-heisler/

textboxfull.com

Learn Python Programming A beginner s guide to learning


the fundamentals of Python language to write efficient
high quality code Romano
https://textbookfull.com/product/learn-python-programming-a-beginner-
s-guide-to-learning-the-fundamentals-of-python-language-to-write-
efficient-high-quality-code-romano/
textboxfull.com
Undergraduate Topics in Computer Science

John Hunt

Advanced Guide
to Python 3
Programming
Undergraduate Topics in Computer Science

Series Editor
Ian Mackie, University of Sussex, Brighton, UK

Advisory Editors
Samson Abramsky, Department of Computer Science, University of Oxford,
Oxford, UK
Chris Hankin, Department of Computing, Imperial College London, London, UK
Dexter C. Kozen, Department of Computer Science, Cornell University, Ithaca, NY,
USA
Andrew Pitts, University of Cambridge, Cambridge, UK
Hanne Riis Nielson , Department of Applied Mathematics and Computer Science,
Technical University of Denmark, Kongens Lyngby, Denmark
Steven S. Skiena, Department of Computer Science, Stony Brook University,
Stony Brook, NY, USA
Iain Stewart, Department of Computer Science, Science Labs, University of
Durham, Durham, UK
Mike Hinchey, University of Limerick, Limerick, Ireland
‘Undergraduate Topics in Computer Science’ (UTiCS) delivers high-quality
instructional content for undergraduates studying in all areas of computing and
information science. From core foundational and theoretical material to final-year
topics and applications, UTiCS books take a fresh, concise, and modern approach
and are ideal for self-study or for a one- or two-semester course. The texts are all
authored by established experts in their fields, reviewed by an international advisory
board, and contain numerous examples and problems, many of which include fully
worked solutions.
The UTiCS concept relies on high-quality, concise books in softback format, and
generally a maximum of 275–300 pages. For undergraduate textbooks that are
likely to be longer, more expository, Springer continues to offer the highly regarded
Texts in Computer Science series, to which we refer potential authors.

More information about this series at http://www.springer.com/series/7592


John Hunt

Advanced Guide to Python 3


Programming

123
John Hunt
Marshfield
Midmarsh Technology Ltd.
Chippenham, Wiltshire, UK

ISSN 1863-7310 ISSN 2197-1781 (electronic)


Undergraduate Topics in Computer Science
ISBN 978-3-030-25942-6 ISBN 978-3-030-25943-3 (eBook)
https://doi.org/10.1007/978-3-030-25943-3
© Springer Nature Switzerland AG 2019
This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part
of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations,
recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission
or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar
methodology now known or hereafter developed.
The use of general descriptive names, registered names, trademarks, service marks, etc. in this
publication does not imply, even in the absence of a specific statement, that such names are exempt from
the relevant protective laws and regulations and therefore free for general use.
The publisher, the authors and the editors are safe to assume that the advice and information in this
book are believed to be true and accurate at the date of publication. Neither the publisher nor the
authors or the editors give a warranty, expressed or implied, with respect to the material contained
herein or for any errors or omissions that may have been made. The publisher remains neutral with regard
to jurisdictional claims in published maps and institutional affiliations.

This Springer imprint is published by the registered company Springer Nature Switzerland AG
The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland
For Denise, my wife.
Preface

Some of the key aspects of this book are:


1. It assumes knowledge of Python 3 and of concepts such as functions, classes,
protocols, Abstract Base Classes, decorators, iterables, collection types (such as
List and Tuple) etc.
2. However, the book assumes very little knowledge or experience of the topics
presented.
3. The book is divided into eight topic areas; Computer graphics, Games, Testing,
File Input/Output, Database Access, Logging, Concurrency and Parallelism and
Network Programming.
4. Each topic in the book has an introductory chapter followed by chapters that
delve into that topic.
5. The book includes exercises at the end of most chapters.
6. All code examples (and exercise solutions) are provided on line in a GitHub
repository.

Chapter Organisation

Each chapter has a brief introduction, the main body of the chapter, followed by a
list of online references that can be used for further reading.
Following this there is typically an Exercises section that lists one or more
exercises that build on the skills you will have learnt in that chapter.
Sample solutions to the exercises are available in a GitHub repository that
supports this book.

vii
viii Preface

What You Need

You can of course just read this book; however following the examples in this book
will ensure that you get as much as possible out of the content.
For this you will need a computer.
Python is a cross platform programming language and as such you can use Python
on a Windows PC, a Linux Box or an Apple Mac etc. This means that you are not tied
to a particular type of operating system; you can use whatever you have available.
However you will need to install some software on your computer. At a mini-
mum you will need Python. The focus of this book is Python 3 so that is the version
that is assumed for all examples and exercises. As Python is available for a wide
range of platforms from Windows, to Mac OS and Linux; you will need to ensure
that you download the version for your operating system.
Python can be downloaded from the main Python web site which can be found at
http://www.python.org.

You will also need some form of editor in which to write your programs. There
are numerous generic programming editors available for different operating systems
with VIM on Linux, Notepad++ on Windows and Sublime Text on Windows and
Macs being popular choices.
Preface ix

However, using a IDE (Integrated Development Environment) editor such as


PyCharm can make writing and running your programs much easier.
However, this book doesn’t assume any particular editor, IDE or environment
(other than Python 3 itself).

Python Versions

Currently there are two main versions of Python called Python 2 and Python 3.
• Python 2 was launched in October 2000 and has been, and still is, very widely used.
• Python 3 was launched in December 2008 and is a major revision to the lan-
guage that is not backward compatible.
The issues between the two versions can be highlighted by the simple print
facility:
• In Python 2 this is written as print ‘Hello World’
• In Python 3 this is written as print (‘Hello World’)
It may not look like much of a difference but the inclusion of the ‘()’ marks a
major change and means that any code written for one version of Python will
probably not run on the other version. There are tools available, such as the 2to3
utility, that will (partially) automate translation from Python 2 to Python 3 but in
general you are still left with significant work to do.
This then raises the question which version to use?
Although interest in Python 3 is steadily increasing there are many organisations
that are still using Python 2. Choosing which version to use is a constant concern
for many companies.
However, the Python 2 end of life plan was initially announced back in 2015 and
although it has been postponed to 2020 out of concern that a large body of existing
code could not easily be forward-ported to Python 3, it is still living on borrowed
time. Python 3 is the future of the Python language and it is this version that has
introduced many of the new and improved language and library features (that have
admittedly been back ported to Python 2 in many cases). This book is solely
focussed on Python 3.

Useful Python Resources

There are a wide range of resources on the web for Python; we will highlight a few
here that you should bookmark. We will not keep referring to these to avoid
repetition but you can refer back to this section whenever you need to:
• https://en.wikipedia.org/wiki/Python_Software_Foundation Python Software
Foundation.
x Preface

• https://docs.python.org/3/ The main Python 3 documentation site. It contains


tutorials, library references, set up and installation guides as well as Python
how-tos.
• https://docs.python.org/3/library/index.html A list of all the builtin features for
the Python language—this is where you can find online documentation for the
various class and functions that we will be using throughout this book.
• https://pymotw.com/3/ the Python 3 Module of the week site. This site contains
many, many Python modules with short examples and explanations of what the
modules do. A Python module is a library of features that build on and expand
the core Python language. For example, if you are interested in building games
using Python then pygame is a module specifically designed to make this easier.
• https://www.fullstackpython.com/email.html is a monthly newsletter that
focusses on a single Python topic each month, such as a new library or module.
• http://www.pythonweekly.com/ is a free weekly summary of the latest Python
articles, projects, videos and upcoming events.
Each section of the book will provide additional online references relevant to the
topic being discussed.

Conventions

Throughout this book you will find a number of conventions used for text styles.
These text styles distinguish between different kinds of information.
Code words, variable and Python values, used within the main body of the text,
are shown using a Courier font. For example:

This program creates a top level window (the wx.Frame) and gives it a title. It also creates
a label (a wx.StaticText object) to be displayed within the frame.

In the above paragraph wx.Frame and wx.StaticText are classes available in a


Python graphical user interface library.
A block of Python code is set out as shown here:
Preface xi

Note that keywords are shown in bold font.


In some cases something of particular interest may be highlighted with colour:

Any command line or user input is shown in italics and coloured purple; for
example:

Or

Example Code and Sample Solutions

The examples used in this book (along with sample solutions for the exercises at the
end of most chapters) are available in a GitHub repository. GitHub provides a web
interface to Git, as well as a server environment hosting Git.
Git is a version control system typically used to manage source code files (such
as those used to create systems in programming languages such as Python but also
Java, C#, C++, Scala etc.). Systems such as Git are very useful for collaborative
development as they allow multiple people to work on an implementation and to
merge their work together. They also provide a useful historical view of the code
(which also allows developers to roll back changes if modifications prove to be
unsuitable).
If you already have Git installed on your computer then you can clone (obtain a
copy of) the repository locally using:
xii Preface

If you do not have Git then you can obtain a zip file of the examples using

You can of course install Git yourself if you wish. To do this see https://git-scm.
com/downloads. Versions of the Git client for Mac OS, Windows and Linux/Unix
are available here.
However, many IDEs such as PyCharm come with Git support and so offer
another approach to obtaining a Git repository.
For more information on Git see http://git-scm.com/doc. This Git guide provides
a very good primer and is highly recommended.

Acknowledgements I would like to thank Phoebe Hunt for creating the pixel images used for the
StarshipMeteors game in Chap. 8.
Contents

1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Part I Computer Graphics


2 Introduction to Computer Graphics . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 The Graphical Computer Era . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.4 Interactive and Non Interactive Graphics . . . . . . . . . . . . . . . . 7
2.5 Pixels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.6 Bit Map Versus Vector Graphics . . . . . . . . . . . . . . . . . . . . . . 10
2.7 Buffering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.8 Python and Computer Graphics . . . . . . . . . . . . . . . . . . . . . . . 10
2.9 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.10 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3 Python Turtle Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2 The Turtle Graphics Library . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2.1 The Turtle Module . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2.2 Basic Turtle Graphics . . . . . . . . . . . . . . . . . . . . . . . 14
3.2.3 Drawing Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2.4 Filling Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.3 Other Graphics Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.4 3D Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.4.1 PyOpenGL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

xiii
xiv Contents

4 Computer Generated Art . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23


4.1 Creating Computer Art . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2 A Computer Art Generator . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.3 Fractals in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.3.1 The Koch Snowflake . . . . . . . . . . . . . . . . . . . . . . . . 28
4.3.2 Mandelbrot Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.4 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5 Introduction to Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5.2 Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.3 Plot Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.4 Matplotlib Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.4.1 Backend Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.4.2 The Artist Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.4.3 The Scripting Layer . . . . . . . . . . . . . . . . . . . . . . . . 41
5.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
6 Graphing with Matplotlib pyplot . . . . . . . . . . . . . . . . . . . . . . . . . . 43
6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
6.2 The pyplot API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
6.3 Line Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
6.3.1 Coded Format Strings . . . . . . . . . . . . . . . . . . . . . . . 46
6.4 Scatter Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
6.4.1 When to Use Scatter Graphs . . . . . . . . . . . . . . . . . . 49
6.5 Pie Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
6.5.1 Expanding Segments . . . . . . . . . . . . . . . . . . . . . . . . 52
6.5.2 When to Use Pie Charts . . . . . . . . . . . . . . . . . . . . . 53
6.6 Bar Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
6.6.1 Horizontal Bar Charts . . . . . . . . . . . . . . . . . . . . . . . 55
6.6.2 Coloured Bars . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
6.6.3 Stacked Bar Charts . . . . . . . . . . . . . . . . . . . . . . . . . 57
6.6.4 Grouped Bar Charts . . . . . . . . . . . . . . . . . . . . . . . . 58
6.7 Figures and Subplots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
6.8 3D Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
6.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
7 Graphical User Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
7.2 GUIs and WIMPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Contents xv

7.3 Windowing Frameworks for Python . . . . . . . . . . . . . . . . . . . . 69


7.3.1 Platform-Independent GUI Libraries . . . . . . . . . . . . . 70
7.3.2 Platform-Specific GUI Libraries . . . . . . . . . . . . . . . . 70
7.4 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
8 The wxPython GUI Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
8.1 The wxPython Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
8.1.1 wxPython Modules . . . . . . . . . . . . . . . . . . . . . . . . . 74
8.1.2 Windows as Objects . . . . . . . . . . . . . . . . . . . . . . . . 75
8.1.3 A Simple Example . . . . . . . . . . . . . . . . . . . . . . . . . 75
8.2 The wx.App Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
8.3 Window Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
8.4 Widget/Control Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
8.5 Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
8.6 Arranging Widgets Within a Container . . . . . . . . . . . . . . . . . . 82
8.7 Drawing Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
8.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
8.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
8.9.1 Simple GUI Application . . . . . . . . . . . . . . . . . . . . . 86
9 Events in wxPython User Interfaces . . . . . . . . . .. . . . . . . . . . . . . . 87
9.1 Event Handling . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . 87
9.2 Event Definitions . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . 87
9.3 Types of Events . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . 88
9.4 Binding an Event to an Event Handler . . . .. . . . . . . . . . . . . . 89
9.5 Implementing Event Handling . . . . . . . . . .. . . . . . . . . . . . . . 89
9.6 An Interactive wxPython GUI . . . . . . . . . .. . . . . . . . . . . . . . 92
9.7 Online Resources . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . 96
9.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . 96
9.8.1 Simple GUI Application . . . . . . .. . . . . . . . . . . . . . 96
9.8.2 GUI Interface to a Tic Tac Toe Game . . . . . . . . . . . 98
10 PyDraw wxPython Example Application . . . . . . . . . . . . . . . . . . . . . 99
10.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
10.2 The PyDraw Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
10.3 The Structure of the Application . . . . . . . . . . . . . . . . . . . . . . 100
10.3.1 Model, View and Controller Architecture . . . . . . . . . 101
10.3.2 PyDraw MVC Architecture . . . . . . . . . . . . . . . . . . . 102
10.3.3 Additional Classes . . . . . . . . . . . . . . . . . . . . . . . . . 103
10.3.4 Object Relationships . . . . . . . . . . . . . . . . . . . . . . . . 104
10.4 The Interactions Between Objects . . . . . . . . . . . . . . . . . . . . . 105
10.4.1 The PyDrawApp . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
10.4.2 The PyDrawFrame Constructor . . . . . . . . . . . . . . . . 106
xvi Contents

10.4.3 Changing the Application Mode . . . . . . . . . . . . . . . 106


10.4.4 Adding a Graphic Object . . . . . . . . . . . . . . . . . . . . 107
10.5 The Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
10.5.1 The PyDrawConstants Class . . . . . . . . . . . . . . . . . . 108
10.5.2 The PyDrawFrame Class . . . . . . . . . . . . . . . . . . . . . 109
10.5.3 The PyDrawMenuBar Class . . . . . . . . . . . . . . . . . . 110
10.5.4 The PyDrawToolBar Class . . . . . . . . . . . . . . . . . . . 111
10.5.5 The PyDrawController Class . . . . . . . . . . . . . . . . . . 111
10.5.6 The DrawingModel Class . . . . . . . . . . . . . . . . . . . . 113
10.5.7 The DrawingPanel Class . . . . . . . . . . . . . . . . . . . . . 113
10.5.8 The DrawingController Class . . . . . . . . . . . . . . . . . . 114
10.5.9 The Figure Class . . . . . . . . . . . . . . . . . . . . . . . . . . 115
10.5.10 The Square Class . . . . . . . . . . . . . . . . . . . . . . . . . . 115
10.5.11 The Circle Class . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
10.5.12 The Line Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
10.5.13 The Text Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
10.6 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
10.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

Part II Computer Games


11 Introduction to Games Programming . . . . . . . . . . . . . . . . . . . . . . . 121
11.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
11.2 Games Frameworks and Libraries . . . . . . . . . . . . . . . . . . . . . 121
11.3 Python Games Development . . . . . . . . . . . . . . . . . . . . . . . . . 122
11.4 Using Pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
11.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
12 Building Games with pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
12.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
12.2 The Display Surface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
12.3 Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
12.3.1 Event Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
12.3.2 Event Information . . . . . . . . . . . . . . . . . . . . . . . . . . 128
12.3.3 The Event Queue . . . . . . . . . . . . . . . . . . . . . . . . . . 129
12.4 A First pygame Application . . . . . . . . . . . . . . . . . . . . . . . . . . 130
12.5 Further Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
12.6 A More Interactive pygame Application . . . . . . . . . . . . . . . . . 136
12.7 Alternative Approach to Processing Input Devices . . . . . . . . . 138
12.8 pygame Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
12.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Contents xvii

13 StarshipMeteors pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141


13.1 Creating a Spaceship Game . . . . . . . . . . . . . . . . . . . . . . . . . . 141
13.2 The Main Game Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
13.3 The GameObject Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
13.4 Displaying the Starship . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
13.5 Moving the Spaceship . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
13.6 Adding a Meteor Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
13.7 Moving the Meteors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
13.8 Identifying a Collision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
13.9 Identifying a Win . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
13.10 Increasing the Number of Meteors . . . . . . . . . . . . . . . . . . . . . 154
13.11 Pausing the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
13.12 Displaying the Game Over Message . . . . . . . . . . . . . . . . . . . . 156
13.13 The StarshipMeteors Game . . . . . . . . . . . . . . . . . . . . . . . . . . 157
13.14 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
13.15 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

Part III Testing


14 Introduction to Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
14.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
14.2 Types of Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
14.3 What Should Be Tested? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
14.4 Testing Software Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
14.4.1 Unit Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
14.4.2 Integration Testing . . . . . . . . . . . . . . . . . . . . . . . . . 169
14.4.3 System Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
14.4.4 Installation/Upgrade Testing . . . . . . . . . . . . . . . . . . 170
14.4.5 Smoke Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
14.5 Automating Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
14.6 Test Driven Development . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
14.6.1 The TDD Cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
14.6.2 Test Complexity . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
14.6.3 Refactoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
14.7 Design for Testability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
14.7.1 Testability Rules of Thumb . . . . . . . . . . . . . . . . . . . 173
14.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
14.9 Book Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
15 PyTest Testing Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
15.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
15.2 What Is PyTest? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
15.3 Setting Up PyTest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
15.4 A Simple PyTest Example . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
xviii Contents

15.5 Working with PyTest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179


15.6 Parameterised Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
15.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
15.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
16 Mocking for Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
16.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
16.2 Why Mock? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
16.3 What Is Mocking? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
16.4 Common Mocking Framework Concepts . . . . . . . . . . . . . . . . 191
16.5 Mocking Frameworks for Python . . . . . . . . . . . . . . . . . . . . . . 192
16.6 The unittest.mock Library . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
16.6.1 Mock and Magic Mock Classes . . . . . . . . . . . . . . . . 193
16.6.2 The Patchers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
16.6.3 Mocking Returned Objects . . . . . . . . . . . . . . . . . . . 195
16.6.4 Validating Mocks Have Been Called . . . . . . . . . . . . 196
16.7 Mock and MagicMock Usage . . . . . . . . . . . . . . . . . . . . . . . . 197
16.7.1 Naming Your Mocks . . . . . . . . . . . . . . . . . . . . . . . 197
16.7.2 Mock Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
16.7.3 Attributes on Mock Classes . . . . . . . . . . . . . . . . . . . 198
16.7.4 Mocking Constants . . . . . . . . . . . . . . . . . . . . . . . . . 199
16.7.5 Mocking Properties . . . . . . . . . . . . . . . . . . . . . . . . . 199
16.7.6 Raising Exceptions with Mocks . . . . . . . . . . . . . . . . 199
16.7.7 Applying Patch to Every Test Method . . . . . . . . . . . 200
16.7.8 Using Patch as a Context Manager . . . . . . . . . . . . . 200
16.8 Mock Where You Use It . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
16.9 Patch Order Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
16.10 How Many Mocks? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
16.11 Mocking Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
16.12 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
16.13 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203

Part IV File Input/Output


17 Introduction to Files, Paths and IO . . . . . . . . . . . . . . . . . . . . . . . . . 207
17.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
17.2 File Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
17.3 Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
17.4 File Input/Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
17.5 Sequential Access Versus Random Access . . . . . . . . . . . . . . . 213
17.6 Files and I/O in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
17.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
Contents xix

18 Reading and Writing Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215


18.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
18.2 Obtaining References to Files . . . . . . . . . . . . . . . . . . . . . . . . 215
18.3 Reading Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
18.4 File Contents Iteration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
18.5 Writing Data to Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
18.6 Using Files and with Statements . . . . . . . . . . . . . . . . . . . . . . 219
18.7 The Fileinput Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
18.8 Renaming Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
18.9 Deleting Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
18.10 Random Access Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
18.11 Directories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
18.12 Temporary Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
18.13 Working with Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
18.14 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
18.15 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
19 Stream IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
19.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
19.2 What is a Stream? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
19.3 Python Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
19.4 IOBase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
19.5 Raw IO/UnBuffered IO Classes . . . . . . . . . . . . . . . . . . . . . . . 234
19.6 Binary IO/Buffered IO Classes . . . . . . . . . . . . . . . . . . . . . . . . 234
19.7 Text Stream Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
19.8 Stream Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
19.9 Closing Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
19.10 Returning to the open() Function . . . . . . . . . . . . . . . . . . . . . . 238
19.11 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
19.12 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
20 Working with CSV Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
20.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
20.2 CSV Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
20.2.1 The CSV Writer Class . . . . . . . . . . . . . . . . . . . . . . 242
20.2.2 The CSV Reader Class . . . . . . . . . . . . . . . . . . . . . . 243
20.2.3 The CSV DictWriter Class . . . . . . . . . . . . . . . . . . . 244
20.2.4 The CSV DictReader Class . . . . . . . . . . . . . . . . . . . 245
20.3 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
20.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
21 Working with Excel Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
21.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
21.2 Excel Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
xx Contents

21.3 The Openpyxl. Workbook Class . . . . . . . . . . . . . . . . . . . . . . 250


21.4 The Openpyxl. WorkSheet Objects . . . . . . . . . . . . . . . . . . . . . 250
21.5 Working with Cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
21.6 Sample Excel File Creation Application . . . . . . . . . . . . . . . . . 251
21.7 Loading a Workbook from an Excel File . . . . . . . . . . . . . . . . 253
21.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
21.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
22 Regular Expressions in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
22.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
22.2 What Are Regular Expressions? . . . . . . . . . . . . . . . . . . . . . . . 257
22.3 Regular Expression Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . 258
22.3.1 Pattern Metacharacters . . . . . . . . . . . . . . . . . . . . . . 259
22.3.2 Special Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . 259
22.3.3 Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
22.4 The Python re Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
22.5 Working with Python Regular Expressions . . . . . . . . . . . . . . . 261
22.5.1 Using Raw Strings . . . . . . . . . . . . . . . . . . . . . . . . . 261
22.5.2 Simple Example . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
22.5.3 The Match Object . . . . . . . . . . . . . . . . . . . . . . . . . . 262
22.5.4 The search() Function . . . . . . . . . . . . . . . . . . . . . . . 263
22.5.5 The match() Function . . . . . . . . . . . . . . . . . . . . . . . 264
22.5.6 The Difference Between Matching and Searching . . . 265
22.5.7 The findall() Function . . . . . . . . . . . . . . . . . . . . . . . 265
22.5.8 The finditer() Function . . . . . . . . . . . . . . . . . . . . . . 266
22.5.9 The split() Function . . . . . . . . . . . . . . . . . . . . . . . . 266
22.5.10 The sub() Function . . . . . . . . . . . . . . . . . . . . . . . . . 267
22.5.11 The compile() Function . . . . . . . . . . . . . . . . . . . . . . 268
22.6 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
22.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270

Part V Database Access


23 Introduction to Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
23.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
23.2 What Is a Database? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
23.2.1 Data Relationships . . . . . . . . . . . . . . . . . . . . . . . . . 276
23.2.2 The Database Schema . . . . . . . . . . . . . . . . . . . . . . . 277
23.3 SQL and Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
23.4 Data Manipulation Language . . . . . . . . . . . . . . . . . . . . . . . . . 280
23.5 Transactions in Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
23.6 Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
Contents xxi

24 Python DB-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283


24.1 Accessing a Database from Python . . . . . . . . . . . . . . . . . . . . 283
24.2 The DB-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
24.2.1 The Connect Function . . . . . . . . . . . . . . . . . . . . . . . 284
24.2.2 The Connection Object . . . . . . . . . . . . . . . . . . . . . . 284
24.2.3 The Cursor Object . . . . . . . . . . . . . . . . . . . . . . . . . 285
24.2.4 Mappings from Database Types to Python Types . . . 286
24.2.5 Generating Errors . . . . . . . . . . . . . . . . . . . . . . . . . . 286
24.2.6 Row Descriptions . . . . . . . . . . . . . . . . . . . . . . . . . . 287
24.3 Transactions in PyMySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
24.4 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
25 PyMySQL Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
25.1 The PyMySQL Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
25.2 Working with the PyMySQL Module . . . . . . . . . . . . . . . . . . . 291
25.2.1 Importing the Module . . . . . . . . . . . . . . . . . . . . . . . 292
25.2.2 Connect to the Database . . . . . . . . . . . . . . . . . . . . . 292
25.2.3 Obtaining the Cursor Object . . . . . . . . . . . . . . . . . . 293
25.2.4 Using the Cursor Object . . . . . . . . . . . . . . . . . . . . . 293
25.2.5 Obtaining Information About the Results . . . . . . . . . 294
25.2.6 Fetching Results . . . . . . . . . . . . . . . . . . . . . . . . . . . 294
25.2.7 Close the Connection . . . . . . . . . . . . . . . . . . . . . . . 295
25.3 Complete PyMySQL Query Example . . . . . . . . . . . . . . . . . . . 295
25.4 Inserting Data to the Database . . . . . . . . . . . . . . . . . . . . . . . . 296
25.5 Updating Data in the Database . . . . . . . . . . . . . . . . . . . . . . . . 298
25.6 Deleting Data in the Database . . . . . . . . . . . . . . . . . . . . . . . . 299
25.7 Creating Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300
25.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
25.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301

Part VI Logging
26 Introduction to Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
26.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
26.2 Why Log? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
26.3 What Is the Purpose of Logging? . . . . . . . . . . . . . . . . . . . . . . 306
26.4 What Should You Log? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
26.5 What Not to Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
26.6 Why Not Just Use Print? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
26.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
27 Logging in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
27.1 The Logging Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
27.2 The Logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
xxii Contents

27.3 Controlling the Amount of Information Logged . . . . . . . . . . . 313


27.4 Logger Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
27.5 Default Logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
27.6 Module Level Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
27.7 Logger Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
27.8 Formatters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
27.8.1 Formatting Log Messages . . . . . . . . . . . . . . . . . . . . 319
27.8.2 Formatting Log Output . . . . . . . . . . . . . . . . . . . . . . 319
27.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
27.10 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
28 Advanced Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
28.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
28.2 Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
28.2.1 Setting the Root Output Handler . . . . . . . . . . . . . . . 325
28.2.2 Programmatically Setting the Handler . . . . . . . . . . . 326
28.2.3 Multiple Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . 328
28.3 Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
28.4 Logger Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
28.5 Performance Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . 333
28.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334

Part VII Concurrency and Parallelism


29 Introduction to Concurrency and Parallelism . . . . . . . . . . . . . . . . . 337
29.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337
29.2 Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337
29.3 Parallelism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339
29.4 Distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
29.5 Grid Computing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
29.6 Concurrency and Synchronisation . . . . . . . . . . . . . . . . . . . . . 342
29.7 Object Orientation and Concurrency . . . . . . . . . . . . . . . . . . . . 342
29.8 Threads V Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
29.9 Some Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
29.10 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
30 Threading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
30.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
30.2 Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
30.3 Thread States . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
30.4 Creating a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
30.5 Instantiating the Thread Class . . . . . . . . . . . . . . . . . . . . . . . . 349
30.6 The Thread Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
Contents xxiii

30.7 The Threading Module Functions . . . . . . . . . . . . . . . . . . . . . . 352


30.8 Passing Arguments to a Thread . . . . . . . . . . . . . . . . . . . . . . . 352
30.9 Extending the Thread Class . . . . . . . . . . . . . . . . . . . . . . . . . . 354
30.10 Daemon Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355
30.11 Naming Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
30.12 Thread Local Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
30.13 Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
30.14 The Global Interpreter Lock . . . . . . . . . . . . . . . . . . . . . . . . . . 359
30.15 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
30.16 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
31 Multiprocessing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
31.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
31.2 The Process Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
31.3 Working with the Process Class . . . . . . . . . . . . . . . . . . . . . . . 365
31.4 Alternative Ways to Start a Process . . . . . . . . . . . . . . . . . . . . 366
31.5 Using a Pool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368
31.6 Exchanging Data Between Processes . . . . . . . . . . . . . . . . . . . 372
31.7 Sharing State Between Processes . . . . . . . . . . . . . . . . . . . . . . 374
31.7.1 Process Shared Memory . . . . . . . . . . . . . . . . . . . . . 374
31.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
31.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
32 Inter Thread/Process Synchronisation . . . . . . . . . . . . . . . . . . . . . . . 377
32.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
32.2 Using a Barrier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
32.3 Event Signalling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
32.4 Synchronising Concurrent Code . . . . . . . . . . . . . . . . . . . . . . . 382
32.5 Python Locks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383
32.6 Python Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
32.7 Python Semaphores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388
32.8 The Concurrent Queue Class . . . . . . . . . . . . . . . . . . . . . . . . . 389
32.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
32.10 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
33 Futures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
33.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
33.2 The Need for a Future . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
33.3 Futures in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396
33.3.1 Future Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
33.3.2 Simple Example Future . . . . . . . . . . . . . . . . . . . . . . 397
33.4 Running Multiple Futures . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
33.4.1 Waiting for All Futures to Complete . . . . . . . . . . . . 400
33.4.2 Processing Results as Completed . . . . . . . . . . . . . . . 402
xxiv Contents

33.5 Processing Future Results Using a Callback . . . . . . . . . . . . . . 403


33.6 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
33.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
34 Concurrency with AsyncIO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
34.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
34.2 Asynchronous IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
34.3 Async IO Event Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
34.4 The Async and Await Keywords . . . . . . . . . . . . . . . . . . . . . . 409
34.4.1 Using Async and Await . . . . . . . . . . . . . . . . . . . . . 409
34.5 Async IO Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
34.6 Running Multiple Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
34.6.1 Collating Results from Multiple Tasks . . . . . . . . . . . 414
34.6.2 Handling Task Results as They Are Made
Available . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
34.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416
34.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417

Part VIII Reactive Programming


35 Reactive Programming Introduction . . . . . . . . . . . . . . . . . . . . . . . . 421
35.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 421
35.2 What Is a Reactive Application? . . . . . . . . . . . . . . . . . . . . . . 421
35.3 The ReactiveX Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422
35.4 The Observer Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422
35.5 Hot and Cold Observables . . . . . . . . . . . . . . . . . . . . . . . . . . . 423
35.5.1 Cold Observables . . . . . . . . . . . . . . . . . . . . . . . . . . 424
35.5.2 Hot Observables . . . . . . . . . . . . . . . . . . . . . . . . . . . 424
35.5.3 Implications of Hot and Cold Observables . . . . . . . . 424
35.6 Differences Between Event Driven Programming and
Reactive Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
35.7 Advantages of Reactive Programming . . . . . . . . . . . . . . . . . . 425
35.8 Disadvantages of Reactive Programming . . . . . . . . . . . . . . . . 426
35.9 The RxPy Reactive Programming Framework . . . . . . . . . . . . . 426
35.10 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
35.11 Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
36 RxPy Observables, Observers and Subjects . . . . . . . . . . . . . . . . . . 429
36.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429
36.2 Observables in RxPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429
36.3 Observers in RxPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
36.4 Multiple Subscribers/Observers . . . . . . . . . . . . . . . . . . . . . . . 432
36.5 Subjects in RxPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
Contents xxv

36.6 Observer Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435


36.6.1 Available Schedulers . . . . . . . . . . . . . . . . . . . . . . . . 437
36.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438
36.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438
37 RxPy Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439
37.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439
37.2 Reactive Programming Operators . . . . . . . . . . . . . . . . . . . . . . 439
37.3 Piping Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
37.4 Creational Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
37.5 Transformational Operators . . . . . . . . . . . . . . . . . . . . . . . . . . 441
37.6 Combinatorial Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . 443
37.7 Filtering Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444
37.8 Mathematical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
37.9 Chaining Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
37.10 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448
37.11 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448

Part IX Network Programming


38 Introduction to Sockets and Web Services . . . . . . . . . . . . . . . . . . . 451
38.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
38.2 Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
38.3 Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
38.4 Addressing Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
38.5 Localhost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
38.6 Port Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
38.7 IPv4 Versus IPv6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
38.8 Sockets and Web Services in Python . . . . . . . . . . . . . . . . . . . 455
38.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
39 Sockets in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
39.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
39.2 Socket to Socket Communication . . . . . . . . . . . . . . . . . . . . . . 457
39.3 Setting Up a Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
39.4 An Example Client Server Application . . . . . . . . . . . . . . . . . . 458
39.4.1 The System Structure . . . . . . . . . . . . . . . . . . . . . . . 458
39.4.2 Implementing the Server Application . . . . . . . . . . . . 459
39.5 Socket Types and Domains . . . . . . . . . . . . . . . . . . . . . . . . . . 461
39.6 Implementing the Client Application . . . . . . . . . . . . . . . . . . . 461
39.7 The Socketserver Module . . . . . . . . . . . . . . . . . . . . . . . . . . . 463
39.8 HTTP Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
39.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
39.10 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
xxvi Contents

40 Web Services in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471


40.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
40.2 RESTful Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
40.3 A RESTful API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
40.4 Python Web Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473
40.5 Flask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474
40.6 Hello World in Flask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474
40.6.1 Using JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474
40.6.2 Implementing a Flask Web Service . . . . . . . . . . . . . 475
40.6.3 A Simple Service . . . . . . . . . . . . . . . . . . . . . . . . . . 475
40.6.4 Providing Routing Information . . . . . . . . . . . . . . . . 476
40.6.5 Running the Service . . . . . . . . . . . . . . . . . . . . . . . . 477
40.6.6 Invoking the Service . . . . . . . . . . . . . . . . . . . . . . . . 478
40.6.7 The Final Solution . . . . . . . . . . . . . . . . . . . . . . . . . 479
40.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
41 Bookshop Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
41.1 Building a Flask Bookshop Service . . . . . . . . . . . . . . . . . . . . 481
41.2 The Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
41.3 The Domain Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482
41.4 Encoding Books Into JSON . . . . . . . . . . . . . . . . . . . . . . . . . . 484
41.5 Setting Up the GET Services . . . . . . . . . . . . . . . . . . . . . . . . . 486
41.6 Deleting a Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 488
41.7 Adding a New Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489
41.8 Updating a Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491
41.9 What Happens if We Get It Wrong? . . . . . . . . . . . . . . . . . . . 492
41.10 Bookshop Services Listing . . . . . . . . . . . . . . . . . . . . . . . . . . . 494
41.11 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497
Chapter 1
Introduction

1.1 Introduction

I have heard many people over the years say that Python is an easy language to lean
and that Python is also a simple language.
To some extent both of these statements are true; but only to some extent.
While the core of the Python language is easy to lean and relatively simple (in
part thanks to its consistency); the sheer richness of the language constructs and
flexibility available can be overwhelming. In addition the Python environment, its
eco system, the range of libraries available, the often competing options available
etc., can make moving to the next level daunting.
Once you have learned the core elements of the language such as how classes
and inheritance work, how functions work, what are protocols and Abstract Base
Classes etc. Where do you go next?
The aim of this book is to delve into those next steps. The book is organised into
eight different topics:
1. Computer Graphics. The book covers Computer Graphics and Computer
Generated Art in Python as well as Graphical User Interfaces and Graphing/
Charting via MatPlotLib.
2. Games Programming. This topic is covered using the pygame library.
3. Testing and Mocking. Testing is an important aspect of any software devel-
opment; this book introduces testing in general and the PyTest module in detail.
It also considers mocking within testing including what and when to mock.
4. File Input/Output. The book covers text file reading and writing as well as
reading and writing CSV and Excel files. Although not strictly related to file
input, regulator expressions are included in this section as they can be used to
process textual data held in files.
5. Database Access. The book introduces databases and relational database in
particular. It then presents the Python DB-API database access standard and

© Springer Nature Switzerland AG 2019 1


J. Hunt, Advanced Guide to Python 3 Programming,
Undergraduate Topics in Computer Science,
https://doi.org/10.1007/978-3-030-25943-3_1
2 1 Introduction

one implementation of this standard, the PyMySQL module used to access a


MySQL database.
6. Logging. An often missed topic is that of logging. The book therefore intro-
duces logging the need for logging, what to log and what not to log as well as
the Python logging module.
7. Concurrency and Parallelism. The book provides extensive coverage of
concurrency topics including Threads, Processes and inter thread or process
synchronisation. It also presents Futures and AsyncIO.
8. Reactive Programming. This section of the book introduces Reactive
Programming using the PyRx reactive programming library.
9. Network Programming. The book concludes by introducing socket and web
service communications in Python.
Each section is introduced by a chapter providing the background and key
concepts of that topic. Subsequent chapters then cover various aspects of the topic.
For example, the first topic covered is on Computer Graphics. This section has
an introductory chapter on Computer Graphics in general. It then introduces the
Turtle Graphics Python library which can be used to generate a graphical display.
The following chapter considers the subject of Computer Generated Art and uses
the Turtle Graphics library to illustrate these ideas. Thus several examples are
presented that might be considered art. The chapter concludes by presenting the
well known Koch Snowflake and the Mandelbrot Fractal set.
This is followed by a chapter presenting the MatPlotLib library used for gen-
erating 2D and 3D charts and graphs (such as a line chart, bar chart or scatter
graph).
The section concludes with a chapter on Graphical User Interfaces (or GUIs)
using the wxpython library. This chapter explores what we mean by a GUI and
some of the alternatives available in Python for creating a GUI.
Subsequent topics follow a similar pattern.
Each programming or library oriented chapter also includes numerous sample
programs that can be downloaded from the GutHub repository and executed. These
chapters also include one or more end of chapter exercises (with sample solutions
also in the GutHub repository).
The topics within the book can be read mostly independently of each other. This
allows the reader to dip into subject areas as and when required. For example, the
File Input/Output section and the Database Access section can be read indepen-
dently of each other (although in this case assessing both technologies may be
useful in selecting an appropriate approach to adopt for the long term persistent
storage of data in a particular system).
Within each section there are usually dependencies, for example it is necessary
to understand the pygame library from the ‘Building Games with pygame’
introductory chapter, before exploring the worked case study presented by the
chapter on the StarshipMeteors game. Similarly it is necessary to have read the
Threading and Multiprocessing chapters before reading the Inter Thread/Process
Synchronisation chapter.
Part I
Computer Graphics
Another Random Scribd Document
with Unrelated Content
"Ja sitten nuora!" jatkoi hän. "Minkälainen mahtaisi se humala olla,
joka panisi ihmisen ensin yrittämään nuoraa uhrinsa kaulan
ympärille, mutta tyytyisi lopulta kiinnittämään sen hänen jalkaansa?
Niin humalassa ei Royce ainakaan ollut, sillä silloin nukkuisi hän nyt
kuin tukki. Ja sitten paras todistus — viskypullo. Te huomautitte, että
juomari tappeli saadakseen viskypullon, onnistuikin saamaan sen,
mutta kieritti sen soppeen vuodattaen puolet sisällöstä permannolle
ja jättäen loput jäljelle. Se on sellaista, jota juomari ei koskaan
tekisi."

Kömpelösti kapusi hän ylös lattialta ja sanoi katuvalla äänellä sille,


joka oli syyttänyt itseään murhasta:

"Olen hyvin pahoillani, hyvä herra, mutta teidän juttunne on hyvin


huonosti keksitty."

"Sir", sanoi Alice Armstrong hiljaa papille, "saanko puhutella teitä


hetkisen kahden kesken."

Tämä pyyntö pakoitti puheliaan papin lähtemään ovelta, ja kun he


olivat tulleet viereiseen huoneeseen, sanoi tyttö hyvin hätäisesti,
ennenkuin toinen oli ehtinyt avata suutaan:

"Te olette teräväjärkinen, ja minä tiedän, että te koetatte pelastaa


Patricken, mutta se ei hyödytä mitään. Asian sisin ydin on musta, ja
mitä pitemmälle te tutkimuksessanne tunkeudutte, sitä enemmän
todisteita löydätte te tuota onnetonta miestä vastaan, jota minä
rakastan."

"Miksi niin?" kysyi Brown katsellen häntä tarkasti.


"Niin", sanoi hän katse yhtä kiinteänä, "siksi, että minä omin silmin
näin hänen tekevän rikoksen."

"Ohoh", sanoi Brown näyttämättä vähääkään liikutetulta. "Ja mitä


hän sitten teki?"

"Minä olin viereisessä huoneessa lähinnä heitä", kertoi tyttö.


"Molemmat ovet olivat kiinni, mutta äkkiä kuulin minä jonkun
ärjäisevän äänellä, jonka vertaista en koskaan ole kuullut: 'Helvetti,
helvetti, helvetti!' Heti sen jälkeen vapisivat ovet ensimäisestä
revolverin laukauksesta. Pamaus toistui kolme kertaa, ennenkuin
sain auki molemmat ovet ja huomasin huoneen olevan täynnä
savua. Mutta mielettömän Patrick-parkani kädessä savusi pistooli, ja
omin silmin näin hänen ampuvan viimeiset laukaukset. Sitten
heittäytyi hän isäni kimppuun, joka kauhuissaan oli kouristautunut
kiinni ikkunalautaan. He taistelivat ja Patrick koetti kuristaa isäni
nuoralla, jonka hän heitti hänen kaulaansa, mutta se liukui
olkapäitten yli jalkoihin. Se kiertyi kai toisen jalan ympärille, sillä
Patrick veti häntä nyt taaksepäin, kuin olisi ollut hullu. Sain käsiini
veitsen, joka oli matolla, syöksyin heidän väliinsä ja taitoin nuoran,
ennenkuin pyörryin."

"Minä ymmärrän", sanoi isä Brown, yhä edelleen kylmän


kohteliaana.
"Minä kiitän teitä."

Kun tyttö nyt vaipui kokoon ja peitti kasvonsa käsillään, meni pappi
jäykkänä ja suorana toiseen huoneeseen, jossa hän tapasi Gilderin
ja Mertonin yksin Patrick Roycen kanssa, joka istui tuolilla
käsiraudoissa.
"Saisinko teidän läsnäollessanne sanoa vangille pari sanaa?"
kysyi isä Brown nöyrällä äänellä poliisipäälliköltä, "ja voisikohan
hänet minuutiksi vapauttaa noista kalvosimista?"

"Hän on vahva mies", sanoi Merton hiljaisella äänellä.

"Miksi tahdotte, että ne otettaisiin pois?"

"Niin", sanoi pappi nöyrästi. "Tahtoisin saada suuren kunnian


puristaa hänen kättään."

Molemmat poliisit tuijottivat häneen, ja isä Brown lisäsi:

"Ettekö tahdo kertoa heille asian oikeaa laitaa?" Tuolilla istuva


mies pudisteli pörröistä päätään, ja pappi kääntyi kärsimättömänä
pois.

"Siinä tapauksessa teen minä sen", sanoi hän. "Yksilön henki on


suuremman arvoinen kuin näennäisesti puhdas maine. Minä aion
pelastaa elossa olevat ja antaa kuolleitten haudata kuolleensa."

Hän meni onnettoman ikkunan luo ja katseli puhuessaan ulos


silmiään räpäytellen:

"Minä sanoin teille, että tässä tapauksessa löysimme monta asetta


ja vain yhden vainajan. Nyt sanon minä teille, että aseita ei käytetty
murhaan. Kaikki nuo kamalat välikappaleet, juoksusilmukka, verinen
veitsi, tyhjä revolveri, kaikkia niitä käytettiin armeliaisuuden
palveluksessa — ei sir Aaronin murhaan, vaan hänen
puolustuksekseen."

"Hänen puolustuksekseen", toisti Gilder. "Ketä vastaan?"


"Häntä itseään vastaan", sanoi isä Brown. "Häntä vaivasi
itsemurhahulluus."

"Mitä ihmeitä?" sanoi Merton epäilevällä äänellä. "Ja ilon


uskonto…"

"Se on julma uskonto", sanoi pappi katsellen ulos ikkunasta.


"Miksei hän olisi saanut itkeä, niinkuin hänen esi-isänsä ennen
häntä? Hänen menettelytapansa jäykistyivät, hänen mielipiteensä
kylmenivät. Tuon iloisen naamion takana piili jumalankieltäjän tyhjä
sielu. Pysyäkseen iloisella asteellaan, jolla hän yleisöön nähden oli,
vaipui hän takaisin juoppouteen, jonka hän kauan sitten oli hylännyt.
Mutta kun rehellinen raittiusmies lankeaa juoppouteen, on siitä se
kamala seuraus, että hän teeskentelee ja odottaa sitä sielullista
helvettiä, josta hän varoittaa muita. Se sai Armstrong paran käsiinsä
ennen aikojaan ja tänä aamuna oli hän niin raivoissaan, että istui
täällä sisällä karjuen olevansa helvetissä, niin hurjalla äänellä, ettei
hänen tyttärensä tuntenut sitä. Hän tahtoi vain kuolla ja mielipuolten
tavallisella viekkaudella oli varustautunut monenlaisilla kuoleman
aseilla — juoksusilmukalla, ystävänsä revolverilla ja veitsellä. Royce
tuli sattumalta sisään ja ryhtyi reippaasti toimeen. Veitsen heitti hän
vanhuksen taakse matolle, sieppasi revolverin, ja kun hänellä ei ollut
aikaa kiskoa ulos kuulia, ampui hän laukauksen laukauksen jälkeen
lattiaan. Itsemurhaaja näki silloin kuoleman edessään toisessa
muodossa ja syöksyi ikkunalle. Royce teki ainoan, mitä tehdä voi —
juoksi hänen jälkeensä nuora käsissään yrittäen sitoa hänen kätensä
ja jalkansa. Silloin juoksi onneton tyttö sisään. Hän käsitti taistelun
väärin ja koetti leikata veitsellä nuoran poikki vapauttaakseen isänsä.
Ensin haavoitti hän Royce-parkaa rystysiin ja niistä juoksi tuo
vähäinen verimäärä. Te huomasitte tietysti, että palvelijan kasvoissa
oli nyrkin iskun jälkeen verta, vaikkei haavaa ollutkaan? Ennen kuin
tyttöparka pyörtyi, oli hänen kuitenkin onnistunut taittaa nuora, niin
että hänen isänsä syöksyi ikkunan kautta ikuisuuteen."

Nyt syntyi pitkä hiljaisuus, jonka hitaasti keskeytti metallin kalina,


kun Gilder irroitti kahleet Patrick Roycen käsistä. Sitten sanoi hän
tälle:

"Teidän asemassanne olisin minä kertonut koko totuuden. Te ja


nuori neiti olette suuremman arvoiset kuin Armstrongin kuolinpuhe."

"Armstrongin kuolinpuheesta välitän minä viisi", huudahti Royce


kiivaasti. "Ettekö käsitä kaiken tapahtuneen sentähden, ettei Alice
saisi tietää mitään?"

"Mistä?" kysyi Merton.

"Siitä, että hän on murhannut isänsä, ettekö sitä käsitä?" huusi


Royce. "Jos häntä ei olisi ollut, olisi ukko vielä elossa. Hän voi tulla
hulluksi saadessaan tietää sen."

"Sitä en juuri luule", sanoi isä Brown tarttuessaan hattuunsa. "Jos


minä olisin teidän sijassanne, sanoisin hänelle kaikki. Pahimmatkaan
erehdykset eivät voi myrkyttää elämää siinä määrin kuin synti. Te
molemmat tulette kaikissa tapauksissa onnellisemmiksi kuin nyt
olette. Minun täytyy mennä takaisin kuuromykkäkouluun."

Kun hän tuli ulos tuuleen, tapasi hän erään tuttavan Highgatestä,
joka pysäytti hänet sanoen:

"Kruununpalvelija on jo täällä. Ruumiinavaus alkaa heti."

- "Minun täytyy mennä takaisin kuuromykkäkouluun", sanoi isä


Brown.
"Valitettavasti en voi jäädä odottamaan ruumiinavauksen tulosta."
RUHTINAS SARADINEN SYNNIT

Otettuaan itselleen kuukauden loman konttoristaan Westminsterissä


Flambeau vietti sen pääasiallisesti pienessä purjeveneessä — niin
pienessä, että se suuren osan aikaa sai käydä soutuveneestä. Hän
oleskeli enimmäkseen itäisen kreivikunnan pienillä vesillä, niin
kapeilla, että vene näytti taikaveneeltä, joka purjehti maalla niittyjen
ja peltomaiden läpi. Aluksessa oli juuri parahiksi tilaa kahdelle
hengelle ja kaikkein välttämättömimmille tarve-esineille. Flambeau
oli varustanut veneensä niillä esineillä, jotka hänen mielestään olivat
välttämättömiä. Ne supistuivat nähtävästi neljään:
lohisäilykepurkkeja siltä varalta, että häntä haluttaisi syödä, pullo
konjakkia, nähtävästi satunnaisen pahoinvoinnin varalta, ladattuja
revolvereja, jos häntä huvittaisi tapella, ja pappi — otaksuttavasti
kuolemantapauksen varalle. Näine kevyine matkatavaroineen hän
rämpi eteenpäin Norfolkin pikku jokia pitkin lopullisena päämääränä
"the Broads", mutta nauttien matkan varrella veteen asti ulottuvista
puutarhoista ja niityistä, kauniista herraskartanoista ja kylistä. Tuon
tuostakin hän pysähtyi kalastamaan poukamissa ja lammikoissa
pysytellen koko ajan rannoilla. [The Norfolk Broads on rannikkoa
lähinnä sijaitseva kreivikunnan osa, jossa tasangolla risteilee virtoja
ja luonnollisia kanavia ja joka siten muistuttaa suuresti Hollantia.]
Flambeaun retkeilyllä ei ollut mitään tarkoitusta, mutta kuten tosi
filosofilla oli hänellä kuitenkin eräs syy. Hänellä oli jonkinlainen
puolitarkoitus, johon hän suhtautui niin vakavasti, että sen
onnistuminen muodosti hänen vapaudenaikansa kruunun, ja niin
kevyesti, ettei sen epäonnistuminen merkinnyt mitään. Monta vuotta
sitten, jolloin hän oli ollut varkaiden kuningas ja Pariisin kuuluisin
mies, hän oli saanut mitä kummallisimpia kirjeitä, joissa hänelle oli
ilmaistu hyväksymistä ja moitetta vieläpä jonkun kerran rakkauttakin.
Varsinkin eräs lähetys oli jäänyt hänen mieleensä. Se sisälsi
käyntikortin kirjekuoressa, johon oli pantu englantilainen postimerkki.
Kortin takasivulle oli vihreällä musteella kirjoitettu ranskaksi: "Jos
joskus vetäydytte pois nykyisestä elämästänne ja tulette
kunnialliseksi ihmiseksi, niin tulkaa tervehtimään minua. Tahdon
tavata teidät, sillä olen tavannut aikamme kaikki muut suuruudet.
Tuo temppu, jolla saitte toisen etsivän vangitsemaan toisen, oli
Ranskan historian loistavimpia." Kortin etusivulle oli painettu
seuraavat sanat: Ruhtinas Saradine, Reed House, Reed Island,
Norfolk.

Siihen aikaan hän ei ollut sen enempää välittänyt tuosta


ruhtinaasta. Hän oli vain saanut selville, että tämä oli ollut loistava ja
huomattava henkilö Etelä-Italiassa. Väitettiin hänen nuoruudessaan
paenneen erään naimisissa olevan korkeasukuisen naisen kanssa.
Tapaus ei sinänsä herättänyt erikoista huomiota ylhäisöpiireissä,
mutta se oli painunut mieleen erään toisen, sen yhteydessä olevan
murhenäytelmän, nimittäin loukatun aviomiehen otaksutun
itsemurhan perusteella. Tämän kerrottiin heittäytyneen alas eräältä
kallionkielekkeeltä Sisiliassa. Ruhtinas asui sitten jonkun aikaa
Wienissä, mutta viimeiset vuodet hän oli viettänyt alituisilla matkoilla.
Kun nyt Flambeau ruhtinaan tavoin oli luopunut eurooppalaisesta
kuuluisuudestaan ja asettunut Englantiin, pälkähti hänen päähänsä
tehdä odottamaton vierailu tuon ylhäisen pakolaisen luo Norfolkiin.
Tämän olinpaikka oli vain hieman vaikeasti löydettävissä, sillä
ruhtinas asui pienessä, syrjäisessä seudussa. Sattuman kautta hän
löysi sen pikemmin kuin luulikaan.

Eräänä iltana he olivat kiinnittäneet veneensä erään korkeata


ruohoa ja lyhyttä katkottua puuta kasvavan penkereen vierustalle.
Kauan ja kiivaasti soudettuaan he asettuivat aikaiseen levolle, ja siitä
taas seurasi, että he heräsivät, ennenkuin oli valjennut, oikeammin
sanottuna, ennen päivän koittoa, sillä suuri sitroonanvärinen kuu oli
juuri laskenut korkean ruohopenkereen taakse, ja taivas oli
sinipunerva väriltään, yöllinen mutta kirkas. Molemmat miehet
muistelivat yhtaikaa lapsuuttaan — tuota lumoavaa, sadunomaista
ikäkautta, jolloin korkeat kasvit puiden tavoin ympäröivät heitä. Suuri
laskeva kuu taustanaan tuhatkaunot ja voikukat näyttivät todella
jättiläissuurilta. Vesi oli niin alhaalla, että kaikki pensaat ja kukat
kohosivat heidän yläpuolelleen.

"Emmekö ole todella kuin keijujen valtakunnassa", sanoi


Flambeau.

Isä Brown, joka istui tikkusuorana veneessä, teki ristinmerkin. Liike


oli niin äkkinäinen, että hänen ystävänsä kysyi häneltä lempeästi ja
ihmeissään, mikä häntä vaivasi.

"Ne, jotka kirjoittivat keskiaikaisia ballaadeja, tunsivat paremmin


keijukaiset kuin me", vastasi pappi. "Keijujen valtakunnassa ei
tapahdu yksinomaan kauniita asioita."

"Pyh, lorua!" sanoi Flambeau. "Näin kauniissa kuutamossa ei voi


tapahtua muuta kuin kaunista. Tahtoisin nyt lähteä eteenpäin ja
nähdä, mitä todella tapahtuu. Ennätämme sekä kuolla että päästä
hautaan, ennenkuin saamme taas tällaisen kuutamon ja tällaisen
tunnelman."

"Kuten haluatte", sanoi isä Brown. "En ole koskaan sanonut, että
aina olisi mieletöntä mennä keijukaisten valtakuntaan. Olen vain
sanonut, että se on aina vaarallista."

He soutivat vaikenevaa virtaa ylöspäin; taivaan syvä sini ja kuun


kalpea hohde heikkenivät yhä enemmän ja vaihtuivat harmaaksi
värittömyydeksi, joka käy päivänkoiton väriloiston edellä. Kun
ensimäiset vienot puna- ja kultajuovat virisivät taivaanrannalle,
katkaisivat joen rannalla heidän edessään sijaitsevan kaupungin tai
kylän mustat ääriviivat ne. Päivä oli jo koittanut ja valaissut kaikki
selvästi heidän liukuessaan pienen kaupungin ulkonevien kattojen ja
siltojen siimekseen. Talot mataline, loivasti viettävine kattoineen
olivat kuin harmaan- ja punaisenkirjava karjalauma, joka on tullut
joen rannalle juomaan. Avartuva ja vaikeneva aamurusko oli jo
muuttunut täydeksi päiväksi, ennenkuin he näkivät ketään elävää
olentoa hiljaisen kaupungin laitureilla ja rantakaduilla. Nyt he
nimittäin näkivät erään hyvin huolettoman ja hyvinvoivan näköisen
miehen paitahihasillaan, miehen, jonka kasvot olivat pyöreät kuin
äsken laskenut kuu ja alaosaltaan punaisen partakiehkuran peitossa.
Hän seisoi pylvääseen nojaten heikosti virtaavan veden partaalla.
Selittämätön mielijohde sai Flambeaun ojentautumaan täyteen
pituuteensa keinuvassa veneessä ja huutamaan miehelle
kysymyksen, tunsiko tämä Reed Islandia [Ruokosaari] ja Reed
Housea [Ruokotalo]. Miehen hymy kävi hieman leveämmäksi, ja hän
tyytyi vastauksen asemesta osoittamaan ylöspäin virran lähintä
polveketta. Flambeau ryhtyi soutamaan sanomatta sen enempää.
Vene sivuutti monta mutkaa ja liukui monen kaislaisen ja tyynen
suvannon yli, mutta ennenkuin etsiminen oli ennättänyt käydä
yksitoikkoiseksi, olivat he kääntyneet hyvin jyrkästä mutkasta ja
tulleet eräänlaiselle lammikolle tai pikku järvelle, jonka näkeminen
vaistomaisesti sai heidät pysähdyttämään veneen. Tämän laajahkon
veden keskellä oli kaikkialta kaislikon ympäröimänä matala, pitkä
saari, jossa oli pitkä, matala bambusta tai jostain muusta
troopillisesta ruo'osta rakennettu talo, bungalow. Seiniä muodostavat
bamburuo'ot olivat vaaleankeltaiset, luisut kattoruovot olivat
tummanpunaiset tai ruskeat, mutta muutoin tuo pitkä talo oli hyvin
yksitoikkoisen ja mitättömän näköinen. Aikainen aamutuuli suhisi
kaisloissa saaren ympärillä ja soi ihmeellisessä ruokotalossa kuin
suunnattoman suuri paimenpilli.

"Tässä se vihdoinkin on", puhkesi Flambeau puhumaan. "Tämä


jos mikä lienee Reed Island, ja tuo talo tuolla lienee kaiketi Reed
House. Luulenpa, että se paksu parrakas mies oli noitaukko."

"Mahdollisesti", sanoi isä Brown puolueettomasti, "mutta siinä


tapauksessa huonoa lajia".

Heidän puhuessaan maltiton Flambeau oli soutanut venheen


maihin kahisevan kaislikon läpi, ja nyt he seisoivat tuolla matalalla
ihmeellisellä saarella tuon kummallisen hiljaisen talon vieressä.

Talo sijaitsi selkäpuoli joelle ja ainoalle maallenousupaikalle päin.


Pääsisäänkäytävä oli toisella pitkällä sivustalla, josta oli näköala
alavaan saaripuutarhaan. Vieraat lähestyivät tätä puutarhaa talon
kolmea sivustaa kiertävää pientä käytävää pitkin, ja saapuivat aivan
lähelle taloa. Kolmesta eri ikkunasta he näkivät erääseen pitkään
valoisaan huoneeseen. Paneli oli vaaleata puuta, seinillä oli joukko
suuria peilejä ja pöydälle oli katettu hieno aamiainen.
Sisäänkäytävän kahden puolen oli asetettu kaksi turkoosinsinistä
kukkaruukkua. Oven avasi synkkäpiirteinen hovimestari, pitkä, laiha,
harmaa ja välinpitämätön — joka mutisi jotain, ettei ruhtinas
Saradine juuri nyt ollut kotona, mutta että häntä odotettiin joka hetki.
Talo oli valmiina ottamaan vastaan häntä ja hänen vieraitaan.
Käyntikortti, jolle vihreällä musteella oli kirjoitettu kutsu, herätti tuon
ahdistetun palvelijasielun pergamenttikasvoille elon kipinän, ja
epäröivän kohteliaasti hän ehdotti, että vieraat jäisivät. "Hänen
ylhäisyytensä voi olla täällä minä hetkenä hyvänsä", sanoi hän, "ja
hän pahastuisi suuresti, ellei hän tapaisi vierasta, jota hän on
pyytänyt tulemaan. Meidän on määrä aina pitää varalla pieni kylmä
aamiainen häntä itseään ja hänen ystäviään varten, ja olen varma,
että hän haluaa sitä tarjottavan nyt, jos suvaitsette."

Flambeau, joka vainusi pientä seikkailua, nyökkäsi ystävällisen


hyväksyvästi ja seurasi vanhaa miestä, joka hyvin juhlallisesti vei
hänet pitkään valoisaan paneloituun huoneeseen. Siellä ei
oikeastaan ollut mitään erikoisen huomattavaa, paitsi tuo hieman
omituinen vaihtelu, jonka aiheuttivat leveät matalat ikkunat ja joukko
matalia leveitä peilejä, heijastaen huoneeseen omituista aavemaista
valoa. Nurkassa oli muutamia tavallisia tauluja — muun muassa
suuri harmaa hyvin nuoren virkapuvussa olevan miehen valokuva ja
kahden pitkätukkaisen pojan punaliidulla tehty luonnos. Flambeaun
kysymykseen, oliko nuori upseeri itse ruhtinas, hovimestari vastasi
lyhyesti kieltävästi — hän oli ruhtinaan nuorempi veli, kapteeni
Stephen Saradine, sanoi hän. Senjälkeen hovimestari kävi hyvin
vaiteliaaksi ja näytti kokonaan kadottaneen halun keskustella
enemmän.

Kun aamiainen oli lopetettu erinomaisella kahvilla ja likööreillä,


vieraat tutustuivat puutarhaan, kirjastoon ja taloudenhoitajattareen,
joka oli tummahko kaunis nainen majesteetillisine ryhteineen ja
madonnamaisine olemuksineen. Hän ja hovimestari tuntuivat olevan
ainoat, jotka olivat jäljellä ruhtinaan ulkomaalaisesta
palveluskunnasta. Talon kaikki muut palvelijat olivat uusia,
taloudenhoitajatar oli valinnut heidät Norfolkista. Taloudenhoitajatar
oli nimeltään rouva Anthony, mutta hän murti hieman italiankielen
tapaan, ja Flambeau oli varma siitä, että Anthony oli norfolkilainen
muunnos latinalaisesta nimestä. Myöskin hovimestari, herra Paul, oli
ulkomuodoltaan hieman ulkomaalainen, mutta puheiltaan ja
tavoiltaan englantilainen, kuten kansainvälisen aateliston
hienoimpien miespuolisten palvelijoiden on laita.

Vaikka paikka oli viehättävä ja omituinen, huokui siitä eräänlainen


synkkyys. Tunnit kuluivat kuin päivät. Pitkät lukuisin ikkunoin
varustetut huoneet olivat tulvillaan päivänvaloa, mutta tämä
päivänvalo oli kuin kuollutta. Ja kaikkien muiden tilapäisten äänien,
kuten puheen, kilisevän lasin tai palvelijoiden askelten yli kuului talon
kaikilta puolilta joen surumielinen kohina.

"Olemme poikenneet väärälle suunnalle ja tulleet väärään


paikkaan", sanoi isä Brown katsahtaen ikkunasta harmaan vihreään
kaislikkoon ja hopeanhohtoiselle joelle. "Mutta mitä se tekee?
Joskus on hyvä olla oikeana henkilönä väärällä paikalla."

Isä Brown oli yleensä vaitelias mutta kuitenkin erittäin


puoleensavetävä pieni pappi, ja näiden harvojen vaikkakin
loppumattoman pitkien tuntien kuluessa hän tunkeutui syvemmälle
Reed Housen salaisuuksiin kuin hänen salapoliisiystävänsä. Hänellä
oli tuo herttaisen vaikenemisen lahja, joka on omiansa herättämään
kertomishalua, ja oikeastaan mitään sanomatta hän sai uusilta
tuttaviltaan tietää enemmän kuin he muuten olisivat kertoneet.
Hovimestari oli luonteeltaan aika umpimielinen. Hän osoittautui
kuitenkin olevansa jörö, melkein eläimellisen uskollinen herraansa
kohtaan, jota hänen sanojensa mukaan oli kohdeltu hyvin pahoin.
Eniten häntä vastaan tuntui rikkoneen hänen ystävänsä veli, jonka
pelkkä nimi venytti tuon vanhan miehen painuneet posket ja sai
hänet nyrpistämään koukkunenäänsä. Kapteeni Stephen oli selvästi
oikea konna, joka oli kiristänyt veljeltänsä suuria rahasummia ja
pahoittanut hänet pakenemaan suuren maailman elämästä tähän
hiljaiseen ja vaatimattomaan soppeen tälle pienelle saarelle.
Enempää Paul ei halunnut sanoa, ja Paul oli ilmeisesti puolueellinen.

Italialainen taloudenhoitajatar oli hieman puheliaampi, Brownin


mielestä senvuoksi, että hän oli tyytymättömämpi. Hänen äänensä
oli jotensakin terävä hänen puhuessaan isännästään, vaikka hän
tuntuikin tuntevan eräänlaista kunnioitusta häntä kohtaan. Flambeau
ja hänen ystävänsä seisoivat peilihuoneessa ja katselivat molempien
veljesten punaliitukuvia, kun taloudenhoitajatar tuli nopeasti sisälle
jollekin asialle. Tällä loistavalla lasihuoneella oli se omituisuus, että
neljä tai viisi peiliä heti heijasti sisääntulijan kuvan, ja ympäri
kääntymättä isä Brown keskeytti lauseensa, joka oli jokin kriitillinen
perhettä koskeva huomautus. Mutta Flambeau, joka nenineen
päivineen oli taulussa kiinni, sanoi lujalla äänellä: "Nämä ovat
luullakseni Saradinen veljekset. Molemmat näyttävät jotensakin
viattomilta. Olisi vaikea sanoa kumpi on hyvä ja kumpi kelvoton."
Kun hän samassa huomasi huoneeseen tulleen naisen, hän käänsi
keskustelun toisaanne ja meni sitten muutaman minuutin kuluttua
puutarhaan. Mutta isä Brown jatkoi kiintein ilmein kuvien tarkastelua,
ja rouva Anthony tarkasteli yhtä huomaavaisena isä Brownia.

Hänellä oli suuret surulliset ruskeat silmät ja hänen oliivinväriset


kasvonsa hehkuivat kummallista tuskaisaa ihmettelyä, ikäänkuin hän
olisi ollut epävarma vieraan olemuksesta — ja tarkoituksesta.
Lieneekö pienen papin puku ja uskonto hänessä herättänyt
etelämaalaisia muistoja ripistä tai luuliko hän tämän tietävän
enemmän kuin tiesi, hän sanoi joka tapauksessa matalalla äänellä,
ikäänkuin olisi puhunut uskotulle: "Ystävänne on tavallaan aivan
oikeassa. Hän sanoo olevan vaikeata ratkaista, kumpi on hyvä,
kumpi kelvoton veli. Kyllä tosiaan olisikin hyvin vaikeata osoittaa
näistä tuo hyvä."

"En ymmärrä teitä", sanoi isä Brown ja aikoi mennä tiehensä.

Nainen meni häntä askeleen lähemmäksi synkin ilmein ja


kumarassa asennossa, sarvensa laskeneen sonnin tavoin.

"Ei kumpainenkaan ole hyvä", sähisi hän. "Kapteeni teki kyllä


pahasti ottaessaan kaikki rahat, mutta minun mielestäni ruhtinas ei
osoittanut suurtakaan hyvyyttä luopuessaan niistä. Kapteeni ei ole
ainoa, josta voidaan sanoa jotakin pahaa."

Papille valkeni jotain hänen seisoessaan kasvot pois käännettyinä,


ja hänen huulensa muodostivat vaieten sanan "kiristystä". Mutta
samassa nainen käänsi äkkiä kalvenneet kasvonsa ja oli vähällä
kaatua. Ovi oli avautunut äänettömästi, ja kalpea Paul seisoi
haamun tavoin oviaukossa. Seinäpeilien vuoksi näytti siltä kuin
huoneeseen olisi astunut samalla kertaa viisi Paulia viidestä eri
ovesta.

"Hänen korkeutensa on juuri saapunut", sanoi hän.

Samalla hetkellä kulki eräs mieshenkilö ensimäisen ikkunan ohitse


ja varjosti aurinkoisen ruudun, ikäänkuin olisi katkaissut voimakkaan
ramppi valon. Heti senjälkeen hän kulki toisen ikkunan ohitse, ja nuo
monet peilit esittivät peräkkäin puitteissaan saman kotkanprofiilin ja
saman reippaan käynnin. Mies oli suora ja joustava, mutta hänen
hiuksensa olivat valkeat ja hänen ihonsa kummallinen,
norsunluunvärinen. Hänellä oli tuo lyhyt kaareva nenä, joka
tavallisesti liittyy pitkiin laihoihin poskiin ja leukaan, mutta nämä
jälkimmäiset olivat osittain viiksien ja piikkiparran peittämät. Viikset
olivat paljon tummemmat kuin piikkiparta ja tekivät teatraalisen
vaikutuksen. Hänen pukunsa sopeutui kasvojen mukaan, sillä
hänellä oli korkea valkea hattu ja kämmekkä napinlävessä, keltaiset
liivit ja pari keltaisia hansikkaita, joita hän kävellessään heilutteli
toisessa kädessään. Kun hän tuli ovelle, kuultiin jäykän Paulin
avaavan sen ja äsken tulleen sanovan iloisesti: "Tässä saatte minut
taas". Jäykkä Paul kumarsi ja vastasi tuskin kuuluvasti, kuten
tapansa oli. Muutaman hetken aikana huoneessa ohjat eivät kuulleet
keskustelua. Mutta sitten hovimestari sanoi: "Kaikki on
käytettävissänne", ja yhä hansikkaitaan heiluttaen ruhtinas Saradine
tuli huoneeseen ja tervehti iloisesti vieraitaan. Taasen nämä näkivät
hämmentävän kuvan — viisi ruhtinasta tuli sisään viidestä ovesta.

Ruhtinas heitti hatun ja keltaiset hansikkaat pöydälle ja ojensi


vieraille sydämellisesti kätensä.

"On ihastuttavaa nähdä teidät täällä, herra Flambeau", sanoi hän.


"Tunnen teidät erittäin hyvin maineeltanne, ellette pidä
sopimattomana, että sanon sen."

"Kaukana siitä", vastasi Flambeau ja nauroi. "Harvat tulevat


kuuluisiksi pelkillä hyveillään."

Ruhtinas loi häneen salamoivan katseen ikäänkuin tutkiakseen,


sisälsikö lause jonkin henkilökohtaisen viittauksen. Mutta sitten
hänkin purskahti nauruun, pyysi toisia istuutumaan ja istuutui itsekin.
"Tämähän on pieni miellyttävä paikka", sanoi hän aivan vapaasti.
"Ikävä vain, ettei täällä ole mitään tekemistä."

Pappi, joka totisena kuin pieni lapsi istui ja tuijotti häneen, joutui
hämärän muiston valtaan, muiston, jota hän ei osannut selittää. Hän
katsoi harmaata huolellisesti käherrettyä tukkaa, keltaisenvalkeita
kasvoja ja hentoa, hieman turhamaista vartaloa. Ruhtinaassa ei kai
ollut mitään luonnotonta, ehkä jotain liioiteltua, mikä johti mieleen
näyttämöllä liikkuvan ihmisen. Tuo selittämätön piili jossakin muussa,
itse kasvojen rakenteessa. Brown kuvitteli yhä nähneensä hänet
ennen. Mies oli kuin valepukuinen vanha ystävä. Mutta sitten hän
muisti äkkiä peilit ja luuli tuon mielikuvan johtuvan noista
monistetuista kuvista.

Ruhtinas Saradine jakoi huolettomasti ja tahdikkaasti


huomaavaisuutensa molemmille vierailleen. Kun hän huomasi
salapoliisin olevan huvitetun urheilusta ja kernaasti käyttävän
hyväkseen lomaansa, vei hän Flambeaun veneineen parhaaseen
onkipaikkaan virralla ja tuli kahdenkymmenen minuutin kuluttua
takaisin omalla kanootillaan mennäkseen isä Brownin luo kirjastoon
ja yhtä kohteliaasti antautuakseen papin filosoofisiin huvituksiin. Hän
näytti tuntevan hyvin sekä kalat että kirjat, vaikkakaan ei kaikkein
rakentavimpia viimemainituista. Hän puhui viittä tai kuutta kieltä. Hän
oli nähtävästi oleskellut eri kaupungeissa ja seurustellut hyvin
kirjavissa seurapiireissä, sillä muutamat hänen hauskimmat juttunsa
koskivat pelihelvettiä ja opiumiluolia, austraalialaisia
"bushrangers'eja" ja italialaisia maantierosvoja. Isä Brown tiesi että
tuo ennen niin juhlittu Saradine oli viettänyt viimeiset vuotensa
melkein alituisilla matkoilla, mutta hän ei pitänyt näitä matkoja
suositeltavina eikä hauskoina.
Maailmanmiehen käytöksestään huolimatta ruhtinas Saradinessa
ilmeni, ainakin niin herkälle huomioidentekijälle kuin isä Brown,
eräänlainen rauhaton, miltei epäluotettava piirre. Hänen kasvonsa
olivat hienostuneet, mutta silmät hurjat. Hän nytkähteli
hermostuneesti, ikäänkuin juopottelu tai morfiini olisi murtanut hänen
terveytensä, ja hän ei kajonnut eikä näyttänyt kajoavan talon
ekonomiseen hallintaan. Se oli kokonaan jätetty molemmille
vanhoille palvelijoille, etupäässä hovimestarille, joka ilmeisesti oli
talon tukipylväs. Paul herra ei itse asiassa ollut hovimestari, vaan
jonkinlainen talouspäällikkö, ellemme sanoisi kamariherra. Hän söi
päivällistä itsekseen, mutta melkein yhtä komeasti kuin herransakin,
koko palveluskunta pelkäsi häntä, ja hän neuvotteli ruhtinaan kanssa
tosin kohteliaasti mutta jotensakin tiukasti, ikäänkuin olisi ollut
ruhtinaan lainopillinen apulainen. Synkkä taloudenhoitajatar oli
häneen verrattuna kuin varjo; hän koetti tehdä itsensä niin
huomaamattomaksi kuin mahdollista ja oli hovimestarin
käskettävissä. Brown ei enää ollut alttiina hänen kuiskailevalle
luottamukselleen ja vihjailuilleen, että nuorempi veli kiristi
vanhempaa. Hänhän ei tiennyt varmasti, missä määrin poissa oleva
kapteeni todella ryösti ruhtinasta, mutta Saradinessa oli jotakin
epävarmaa ja salaperäistä, joka teki asian hyvinkin uskottavaksi.

Kun he taas tulivat peilisaliin, alkoi veden ja piilipuiden


reunustamien rantojen yli laskeutua illan hämy. Isä Brownin valtasi
taas kummallinen tunne kuin olisi hän jossain synkässä ja
surullisessa satumaassa. "Voi jospa Flambeau olisi taas täällä!"
ajatteli hän.

"Uskotteko tuomioon?" kysyi levoton ruhtinas Saradine äkkiä.

"En", vastasi hänen vieraansa, "uskon tuomiopäivään."


Ruhtinas kääntyi ikkunasta ja tuijotti niin kummallisesti häneen.
Ruhtinas seisoi itse selkä laskevaan aurinkoon päin, niin että hänen
kasvonsa olivat varjossa. "Mitä tarkoitatte?" kysyi hän.

"Tarkoitan, että me täällä olemme esiripun väärällä puolella",


vastasi isä Brown. "Asioilla, jotka täällä tapahtuvat, ei tunnu olevan
mitään merkitystä, mutta ne merkitsevät paljon eräässä toisessa
paikassa. Toisessa paikassa todellista rikoksellista kohtaa
rangaistus. Täällä näyttää usein siltä kuin rangaistus kohtaisi väärää
henkilöä."

Ruhtinas päästi selittämättömän, melkein eläimellisen äänen.


Hänen silmänsä loistivat kummallisesti. Isä Brownissa heräsi uusi
epäilys. Olikohan olemassa toinen selitys tuohon Saradinen
loistavien päähänpistojen ja jyrkkien muutosten vaihteluun. Olikohan
ruhtinas — tokko hän oli oikein viisas? Saradine toisti sanoja "väärää
henkilöä — väärää henkilöä" useammin kuin oli luonnollista
tavallisessa keskustelussa.

Mutta sitten isä Brownille valkeni vielä eräs totuus.

Hän näki peileistä, että äänetön ovi avautui ja huoneeseen astui


vaitelias Paul herra kalpeana ja tunteettomana kuten tavallisesti.

"Pidin parhaana", sanoi hän vanhan perhepalvelijan jäykällä


kunnioituksella, "pidin parhaana heti ilmoittaa, että kuuden miehen
soutama vene on laskenut siltaan ja että perässä istuu herrasmies."

"Vene!" toisti ruhtinas. "Herrasmieskö?" ja hän nousi.

Hämmästystä ilmaisevan äänettömyyden katkaisi ainoastaan


kaulushaikaran kummallinen uikutus kaislikossa. Ennenkuin kukaan
ennätti toipua ja sanoa mitään, nähtiin uusien kasvojen sivuuttavan
nuo kolme aurinkoista ikkunaa, joiden ohi ruhtinas pari tumia sitten
oli kulkenut. Mutta kaarevaa nenää lukuunottamatta näissä
kasvoissa ei ollut paljoa ruhtinaan kasvoista muistettavaa. Saradinen
uuden valkean hatun asemesta nähtiin tässä musta vanhanaikainen
ja ulkolaiskuosinen; hatun alta näkyivät nuoret hyvin vakavat,
sileäksiajetut, lujan leuan vaiheilta sinertävät ja hieman Napoleonia
muistuttavat kasvot. Mielikuvaa tuki koko puvun vanhuus ja
omituisuus, mikä osoitti, että hän oli mies, joka ei välittänyt muuttaa
isiensä aikana vallinnutta muotia. Hänen yllään oli kulunut pitkä
takki, punaiset sotilasmaiset liivit ja valkeat karkeat housut, jollaisia
yleisesti käytettiin kuningatar Viktorian hallituksen alkuaikoina, mutta
jotka meidän päivinämme tekevät vanhentuneen vaikutuksen.
Kaikkein näiden vaatekappalten keskellä hänen kasvonsa näyttivät
kummallisen nuorilta ja tavattoman teeskentelemättömiltä.

"Voi p-ru!" sanoi ruhtinas Saradine asettaessaan valkean hatun


päähänsä ja mennessään eteisen ovelle, jonka hän itse aukaisi
laskevan auringon valaisemaan puutarhaan päin.

Vastatullut ja hänen seuralaisensa olivat juuri ennättäneet asettua


ruohokentälle ikäänkuin pieni näyttelijäjoukkue. Nuo kuusi soutajaa
olivat vetäneet veneen rannalle ja vartioivat sitä melkein uhkaavan
näköisinä, sillä he pitivät aironsa ojossa kuten keihäät. He olivat
tummaihoisia miehiä ja muutamilla heistä oli renkaat korvissa. Eräs
soutajista astui kuitenkin esille tuon nuoren miehen rinnalle, jolla oli
oliivin väriset kasvot ja punaiset liivit. Tällä miehellä oli suuri
kummallisenmuotoinen kotelo kainalossa.

"Onko nimenne", sanoi nuori mies, "Saradine?"

Saradine nyökäytti huolettomasti myöntäen.


Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

textbookfull.com

You might also like