Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
100% found this document useful (3 votes)
12 views

Advanced Guide to Python 3 Programming, 2nd John Hunt all chapter instant download

Hunt

Uploaded by

ishkovbarfi
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (3 votes)
12 views

Advanced Guide to Python 3 Programming, 2nd John Hunt all chapter instant download

Hunt

Uploaded by

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

Download Full Version ebook - Visit ebookmeta.

com

Advanced Guide to Python 3 Programming, 2nd John


Hunt

https://ebookmeta.com/product/advanced-guide-to-
python-3-programming-2nd-john-hunt/

OR CLICK HERE

DOWLOAD NOW

Discover More Ebook - Explore Now at ebookmeta.com


Instant digital products (PDF, ePub, MOBI) ready for you
Download now and discover formats that fit your needs...

Start reading on any device today!

A Beginners Guide to Python 3 Programming 2nd Edition John


Hunt

https://ebookmeta.com/product/a-beginners-guide-to-
python-3-programming-2nd-edition-john-hunt/

ebookmeta.com

Beginner s Guide to Kotlin Programming John Hunt

https://ebookmeta.com/product/beginner-s-guide-to-kotlin-programming-
john-hunt/

ebookmeta.com

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


Programming - 2nd ed 2nd Edition Irv Kalb

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

ebookmeta.com

Brewer s Luck 1st Edition James Keffer

https://ebookmeta.com/product/brewer-s-luck-1st-edition-james-keffer/

ebookmeta.com
Business Accounting and Finance 5th Edition Catherine
Gowthorpe

https://ebookmeta.com/product/business-accounting-and-finance-5th-
edition-catherine-gowthorpe/

ebookmeta.com

Thrown to her Wolves 1st Edition Margo Bond Collins

https://ebookmeta.com/product/thrown-to-her-wolves-1st-edition-margo-
bond-collins/

ebookmeta.com

The Shadows Black Dagger Brotherhood 13 First Edition J R


Ward

https://ebookmeta.com/product/the-shadows-black-dagger-
brotherhood-13-first-edition-j-r-ward/

ebookmeta.com

Psychological Interventions for Psychosis: Towards a


Paradigm Shift Juan Antonio Díaz-Garrido

https://ebookmeta.com/product/psychological-interventions-for-
psychosis-towards-a-paradigm-shift-juan-antonio-diaz-garrido/

ebookmeta.com

Essential Oils: Extraction, Characterization and


Applications Gulzar Ahmad Nayik

https://ebookmeta.com/product/essential-oils-extraction-
characterization-and-applications-gulzar-ahmad-nayik/

ebookmeta.com
The Cambridge Companion to Wagner s Der Ring des
Nibelungen Cambridge Companions to Music 1st Edition Mark
Berry
https://ebookmeta.com/product/the-cambridge-companion-to-wagner-s-der-
ring-des-nibelungen-cambridge-companions-to-music-1st-edition-mark-
berry/
ebookmeta.com
Undergraduate Topics in Computer Science

John Hunt

Advanced Guide
to Python 3
Programming
Second Edition
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
Mike Hinchey , Lero – The Irish Software Research Centre, University of
Limerick, Limerick, Ireland
Dexter C. Kozen, Department of Computer Science, Cornell University, Ithaca,
NY, USA
Andrew Pitts , Department of Computer Science and Technology, 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, Durham University, Durham,
UK
Joseph Migga Kizza, College of Engineering and Computer Science, The
University of Tennessee-Chattanooga, Chattanooga, TN, USA
‘Undergraduate Topics in Computer Science’ (UTiCS) delivers high-quality instruc-
tional 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.
John Hunt

Advanced Guide to Python 3


Programming
Second Edition
John Hunt
Midmarsh Technology Ltd.
Chippenham, Wiltshire, UK

ISSN 1863-7310 ISSN 2197-1781 (electronic)


Undergraduate Topics in Computer Science
ISBN 978-3-031-40335-4 ISBN 978-3-031-40336-1 (eBook)
https://doi.org/10.1007/978-3-031-40336-1

© Springer Nature Switzerland AG 2019, 2023

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, my soulmate, my best
friend.
Preface to the Second Edition

This second edition represents a significant expansion of the material in the first
edition, as well as an update of that book from Python 3.7 to 3.12.
This book includes whole new sections on advanced language features, Reactive
Programming in Python and data analysts. New chapters on working with Tkinter,
on event handling with Tkinter and a simple drawing application using Tkinter have
been added. A new chapter on performance monitoring and profiling has also been
added. A chapter on pip and conda is included at the end of the book.
In all there are 18 completely new chapters that take you far further on your Python
journey. Enjoy the book and I hope you find it useful.

Chippenham, UK John Hunt

vii
Preface to the First Edition

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 and collection types (such
as list and tuple).
2. However, the book assumes very little knowledge or experience of the topics
presented.
3. The book is divided into eleven topic areas: advanced language features,
Computer Graphics, games, testing, file input/output, database access, logging,
concurrency and parallelism, Reactive Programming, network programming and
data analytics.
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.

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, an Apple Mac, etc. So 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 that computer. At a minimum
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

ix
x Preface to the First Edition

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 website which can be found at
http://www.python.org/.

You will also need some form of editor 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.
However, using an Integrated Development Environment (IDE) editor such as
PyCharm, Visual Studio Code or Spyder can make writing and running your programs
much easier.
However, this book does not assume any particular editor, IDE or environment
(other than Python 3 itself).

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. A block of Python code is set out as shown here:
Preface to the First Edition xi

def draw_koch(size, depth):


if depth > 0:
for angle in ANGLES:
draw_koch(size / 3, depth - 1)
turtle.left(angle)
else:
turtle.forward(size)
# Draw three sides of snowflake
for_in range(3):
draw_koch(SIZE_OF_SNOWFLAKE, depth)
turtle.right(120)

Note that keywords and points of interest are shown in bold font.
Any command line or user input is shown in standard font as shown below, for
example:
Hello, world
Enter your name: John
Hello John

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++ and Scala). 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).
The GitHub repository for this book can be found at:
• https://github.com/johnehunt/advancedpython3_2nd
If you already have Git installed on your computer, then you can clone (obtain a
copy of) the repository locally using:
git clone https://github.com/johnehunt/advancedpyth
on3_2nd.git
If you do not have Git, then you can obtain a zip file of the examples using
https://github.com/johnehunt/advancedpython3_2nd/arc
hive/refs/heads/main.zip
xii Preface to the First Edition

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.

Acknowledgement I would like to thank Phoebe Hunt for creating the pixel images used for the
Starship Meteors game in Chap. 22.
Contents

1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Useful Python Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Part I Advanced Language Features


2 Python Type Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 Pythons Type System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3 The Challenge for Python Developers . . . . . . . . . . . . . . . . . . . . . . 8
2.4 Static Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.5 Python Type Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.6 Type Hint Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.7 Type Hints for Multiple Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.8 The Self Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.9 The Benefits of Type Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.10 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.11 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3 Class Slots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.2 The Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.3 Slots to the Rescue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.4 Performance Benefits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.5 Why Not Use Slots? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.6 Online Resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4 Weak References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2 How Garbage Collection Works: Reference Counting . . . . . . . . 23
4.3 Weak References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.4 When to Use Weak References . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

xiii
xiv Contents

4.5 The Weakref Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26


4.6 Creating Weak References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.7 Retrieving Objects from Weak References . . . . . . . . . . . . . . . . . . 28
4.8 The WeakValueDicitonary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.9 WeakKeyDictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.10 Proxy Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.11 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5 Data Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.2 A Traditional Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.3 Defining Data Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5.4 Defining Additional Behaviour . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.5 The Dataclass Decorator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.6 Custom Factory for Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.7 Immutable Dataclasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.8 Data Classes and Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.9 Post Initialisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.10 Initialisation Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.11 Positional Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.12 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
6 Structural Pattern Matching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6.2 The Match Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6.3 Matching Classes with Positional Attributes . . . . . . . . . . . . . . . . . 50
6.4 Matching Against Standard Classes . . . . . . . . . . . . . . . . . . . . . . . . 51
6.5 Online Resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
7 Working with pprint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7.2 The pprint Data Printer Module . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7.3 Basic pprint Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.4 Changing the Width . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.5 Changing the Depth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.6 Managing the Indentation Level . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.7 Reducing Line Breaks Using Compact . . . . . . . . . . . . . . . . . . . . . 59
7.8 The pformat Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
7.9 The saferepr() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
7.10 Using the PrettyPrinter Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
7.11 Online Resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
8 Shallow v Deep Copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
8.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
8.2 Copying a List of Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
8.3 The Problem with Copying . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Contents xv

8.4 The Copy Module to the Rescue . . . . . . . . . . . . . . . . . . . . . . . . . . . 68


8.5 Using the deepcopy() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
8.6 Online Resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
9 The __init__ Versus __new__ and __call . . . . . . . . . . . . . . . . . . . . . . . . . 71
9.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
9.2 The __new__ and __init__ Methods . . . . . . . . . . . . . . . . . . . . . . . 71
9.3 The __new__ Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
9.4 When to Use the __new__ Method . . . . . . . . . . . . . . . . . . . . . . . . . 73
9.5 Using __new__ to Create a Singleton Object . . . . . . . . . . . . . . . . 74
9.6 The __init__ Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
9.7 Can __new__ and __init__ Be Used Together? . . . . . . . . . . . . . . 76
9.8 The __call__ Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
9.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
10 Python Metaclasses and Meta Programming . . . . . . . . . . . . . . . . . . . . . 79
10.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
10.2 Metaprogramming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
10.3 Decorators as a Form of Metaprogramming . . . . . . . . . . . . . . . . . 81
10.4 Metaclasses for Metaprogramming . . . . . . . . . . . . . . . . . . . . . . . . 83
10.4.1 Singleton Metaclass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
10.5 Exec and Eval for Metaprogramming . . . . . . . . . . . . . . . . . . . . . . 85
10.5.1 The exec() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
10.5.2 The eval() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
10.5.3 eval Versus exec() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

Part II Computer Graphics and GUIs


11 Introduction to Computer Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
11.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
11.2 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
11.3 The Graphical Computer Era . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
11.4 Interactive and Non Interactive Graphics . . . . . . . . . . . . . . . . . . . . 93
11.5 Pixels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
11.6 Bit Map Versus Vector Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
11.7 Buffering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
11.8 Python and Computer Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
11.9 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
11.10 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
12 Python Turtle Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
12.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
12.2 The Turtle Graphics Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
12.2.1 The Turtle Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
12.2.2 Basic Turtle Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
12.2.3 Drawing Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
12.2.4 Filling Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
xvi Contents

12.3 Other Graphics Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105


12.4 3D Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
12.4.1 PyOpenGL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
12.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
12.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
13 Computer Generated Art . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
13.1 Creating Computer Art . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
13.2 A Computer Art Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
13.3 Fractals in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
13.4 The Koch Snowflake . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
13.5 Mandelbrot Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
13.6 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
13.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
14 Introduction to Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
14.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
14.2 Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
14.3 Plot Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
14.4 Matplotlib Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
14.4.1 Backend Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
14.4.2 The Artist Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
14.4.3 The Scripting Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
14.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
15 Graphing with Matplotlib Pyplot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
15.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
15.2 The pyplot API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
15.3 Line Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
15.3.1 Coded Format Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
15.4 Scatter Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
15.4.1 When to Use Scatter Graphs . . . . . . . . . . . . . . . . . . . . . 134
15.5 Pie Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
15.5.1 Expanding Segments . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
15.5.2 When to Use Pie Charts . . . . . . . . . . . . . . . . . . . . . . . . . 138
15.6 Bar Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
15.6.1 Horizontal Bar Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
15.6.2 Coloured Bars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
15.6.3 Stacked Bar Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
15.6.4 Grouped Bar Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
15.7 Figures and Subplots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
15.8 3D Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
15.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Contents xvii

16 Graphical User Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151


16.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
16.2 GUIs and WIMPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
16.3 Windowing Frameworks for Python . . . . . . . . . . . . . . . . . . . . . . . . 153
16.3.1 Platform-Independent GUI Libraries . . . . . . . . . . . . . . 154
16.3.2 Platform-Specific GUI Libraries . . . . . . . . . . . . . . . . . . 154
16.4 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
17 Tkinter GUI Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
17.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
17.2 Tkinter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
17.3 Windows as Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
17.4 Key Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
17.4.1 The Tk Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
17.4.2 TK Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
17.4.3 The TopLevel Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
17.4.4 The Frame Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
17.4.5 Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
17.4.6 The Canvas Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
17.5 The Class Inheritance Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
17.5.1 Layout Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
17.6 A Simple Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
17.7 Tkinter Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
17.7.1 Mac Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
17.7.2 Windows Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
17.8 GUI Builders for Tkinter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
17.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
17.10 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
18 Events in Tkinter User Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
18.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
18.2 Event Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
18.3 What is Event Handling? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
18.4 What Are Event Handlers? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
18.5 Event Binders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
18.6 Virtual Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
18.7 Event Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
18.8 What Types of Event Are There? . . . . . . . . . . . . . . . . . . . . . . . . . . 174
18.9 Binding an Event to an Event Handler . . . . . . . . . . . . . . . . . . . . . . 175
18.10 Implementing Event Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
18.11 An Interactive GUI Application . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
18.12 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
18.13 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
xviii Contents

19 PyDraw Tkinter Example Application . . . . . . . . . . . . . . . . . . . . . . . . . . 185


19.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
19.2 The PyDraw Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
19.3 The Structure of the Application . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
19.3.1 Model, View and Controller Architecture . . . . . . . . . . 188
19.3.2 PyDraw MVC Architecture . . . . . . . . . . . . . . . . . . . . . . 189
19.3.3 Additional Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
19.3.4 Object Relationships . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
19.4 The Interactions Between Objects . . . . . . . . . . . . . . . . . . . . . . . . . 191
19.4.1 The PyDrawApp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
19.5 The PyDrawView Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
19.5.1 Changing the Application Mode . . . . . . . . . . . . . . . . . . 193
19.5.2 Adding a Graphic Object . . . . . . . . . . . . . . . . . . . . . . . . 193
19.6 The Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
19.6.1 The PyDrawConstants Class . . . . . . . . . . . . . . . . . . . . . 194
19.6.2 The PyDrawView Class . . . . . . . . . . . . . . . . . . . . . . . . . 195
19.6.3 The PyDrawMenuBar Class . . . . . . . . . . . . . . . . . . . . . . 196
19.6.4 The PyDrawController Class . . . . . . . . . . . . . . . . . . . . . 196
19.6.5 The DrawingModel Class . . . . . . . . . . . . . . . . . . . . . . . . 197
19.6.6 The DrawingView Class . . . . . . . . . . . . . . . . . . . . . . . . . 198
19.6.7 The DrawingController Class . . . . . . . . . . . . . . . . . . . . . 198
19.6.8 The Figure Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
19.6.9 The Square Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
19.6.10 The Circle Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
19.6.11 The Line Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
19.6.12 The Text Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
19.7 Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
19.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201

Part III Computer Games


20 Introduction to Games Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
20.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
20.2 Games Frameworks and Libraries . . . . . . . . . . . . . . . . . . . . . . . . . 205
20.3 Python Games Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
20.4 Using Pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
20.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
21 Building Games with Pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
21.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
21.2 The Display Surface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
21.3 Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
21.3.1 Event Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
21.3.2 Event Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
21.3.3 The Event Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
Contents xix

21.4 A First pygame Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214


21.5 Further Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
21.6 A More Interactive pygame Application . . . . . . . . . . . . . . . . . . . . 219
21.7 Alternative Approach to Processing Input Devices . . . . . . . . . . . 221
21.8 pygame Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
21.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
22 StarshipMeteors Pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
22.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
22.2 Creating a Spaceship Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
22.3 The Main Game Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
22.4 The GameObject Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
22.5 Displaying the Starship . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
22.6 Moving the Spaceship . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
22.7 Adding a Meteor Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
22.8 Moving the Meteors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
22.9 Identifying a Collision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
22.10 Identifying a Win . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
22.11 Increasing the Number of Meteors . . . . . . . . . . . . . . . . . . . . . . . . . 238
22.12 Pausing the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
22.13 Displaying the Game Over Message . . . . . . . . . . . . . . . . . . . . . . . 239
22.14 The StarshipMeteors Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
22.15 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
22.16 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244

Part IV Testing
23 Introduction to Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
23.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
23.2 Types of Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
23.3 What Should Be Tested? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
23.4 Types of Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
23.4.1 Unit Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
23.4.2 Integration Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
23.4.3 System Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
23.4.4 Installation/Upgrade Testing . . . . . . . . . . . . . . . . . . . . . 252
23.4.5 Smoke Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
23.5 Automating Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
23.6 Test-Driven Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
23.6.1 The TDD Cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
23.6.2 Test Complexity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
23.6.3 Refactoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
23.7 Design for Testability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
23.7.1 Testability Rules of Thumb . . . . . . . . . . . . . . . . . . . . . . 255
23.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
23.9 Book Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
xx Contents

24 PyTest Testing Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257


24.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
24.2 What is PyTest? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
24.3 Setting up PyTest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
24.4 A Simple PyTest Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
24.5 Working with PyTest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
24.6 Parameterised Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
24.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
24.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
25 Mocking for Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
25.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
25.2 Why Mock? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
25.3 What is Mocking? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
25.4 Common Mocking Framework Concepts . . . . . . . . . . . . . . . . . . . 273
25.5 Mocking Frameworks for Python . . . . . . . . . . . . . . . . . . . . . . . . . . 274
25.6 The Unittest.Mock Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
25.6.1 Mock and Magic Mock Classes . . . . . . . . . . . . . . . . . . . 275
25.6.2 The Patchers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
25.6.3 Mocking Returned Objects . . . . . . . . . . . . . . . . . . . . . . . 277
25.6.4 Validating Mocks Have Been Called . . . . . . . . . . . . . . . 278
25.7 Mock and MagicMock Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
25.7.1 Naming Your Mocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
25.7.2 Mock Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
25.7.3 Attributes on Mock Classes . . . . . . . . . . . . . . . . . . . . . . 279
25.7.4 Mocking Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
25.7.5 Mocking Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
25.7.6 Raising Exceptions with Mocks . . . . . . . . . . . . . . . . . . . 281
25.7.7 Applying Patch to Every Test Method . . . . . . . . . . . . . 281
25.7.8 Using Patch as a Context Manager . . . . . . . . . . . . . . . . 281
25.8 Mock Where You Use It . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
25.9 Patch Order Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
25.10 How Many Mocks? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
25.11 Mocking Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
25.12 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
25.13 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284

Part V File Input/Output


26 Introduction to Files, Paths and IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
26.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
26.2 File Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
26.3 Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
26.4 File Input/Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
Contents xxi

26.5 Sequential Access versus Random Access . . . . . . . . . . . . . . . . . . 296


26.6 Files and I/O in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
26.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
27 Reading and Writing Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
27.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
27.2 Obtaining References to Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
27.3 Reading Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
27.4 File Contents Iteration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
27.5 Writing Data to Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
27.6 Using Files and with Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
27.7 The Fileinput Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
27.8 Renaming Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
27.9 Deleting Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
27.10 Random Access Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
27.11 Directories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
27.12 Temporary Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
27.13 Working with Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
27.14 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
27.15 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
28 Stream IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
28.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
28.2 What is a Stream? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
28.3 Python Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
28.4 IOBase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
28.5 Raw IO/UnBuffered IO Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
28.6 Binary IO/Buffered IO Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
28.7 Text Stream Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
28.8 Stream Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
28.9 Closing Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
28.10 Returning to the Open() Function . . . . . . . . . . . . . . . . . . . . . . . . . . 322
28.11 Online Resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
28.12 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
29 Working with CSV Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
29.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
29.2 CSV Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
29.2.1 The CSV Writer Class . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
29.2.2 The CSV Reader Class . . . . . . . . . . . . . . . . . . . . . . . . . . 327
29.2.3 The CSV DictWriter Class . . . . . . . . . . . . . . . . . . . . . . . 328
29.2.4 The CSV DictReader Class . . . . . . . . . . . . . . . . . . . . . . 329
29.3 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
29.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
xxii Contents

30 Working with Excel Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333


30.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
30.2 Excel Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
30.3 The Openpyxl. Workbook Class . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
30.4 The Openpyxl. WorkSheet Objects . . . . . . . . . . . . . . . . . . . . . . . . . 334
30.5 Working with Cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
30.6 Sample Excel File Creation Application . . . . . . . . . . . . . . . . . . . . 335
30.7 Loading a Workbook from an Excel File . . . . . . . . . . . . . . . . . . . . 336
30.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
30.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
31 Regular Expressions in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
31.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
31.2 What Are Regular Expressions? . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
31.3 Regular Expression Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
31.3.1 Pattern Metacharacters . . . . . . . . . . . . . . . . . . . . . . . . . . 342
31.3.2 Special Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
31.3.3 Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
31.4 The Python re Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
31.5 Working with Python Regular Expressions . . . . . . . . . . . . . . . . . . 345
31.5.1 Using Raw Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
31.5.2 Simple Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
31.5.3 The Match Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
31.5.4 The search() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
31.5.5 The match() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
31.5.6 The Difference Between Matching
and Searching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
31.5.7 The finadall() Function . . . . . . . . . . . . . . . . . . . . . . . . . . 349
31.5.8 The finditer() Function . . . . . . . . . . . . . . . . . . . . . . . . . . 349
31.5.9 The split() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
31.5.10 The sub() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
31.5.11 The compile() Function . . . . . . . . . . . . . . . . . . . . . . . . . . 351
31.6 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
31.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354

Part VI Database Access


32 Introduction to Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
32.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
32.2 What Is a Database? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
32.2.1 Data Relationships . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
32.2.2 The Database Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . 361
32.3 SQL and Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
32.4 Data Manipulation Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
32.5 Transactions in Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
32.6 Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
Contents xxiii

33 Python DB-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369


33.1 Accessing a Database from Python . . . . . . . . . . . . . . . . . . . . . . . . 369
33.2 The DB-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
33.2.1 The Connect Function . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
33.2.2 The Connection Object . . . . . . . . . . . . . . . . . . . . . . . . . . 370
33.2.3 The Cursor Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
33.2.4 Mappings from Database Types to Python Types . . . . 372
33.2.5 Generating Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
33.2.6 Row Descriptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
33.3 Transactions in PyMySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
33.4 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
34 PyMySQL Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
34.1 The PyMySQL Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
34.2 Working with the PyMySQL Module . . . . . . . . . . . . . . . . . . . . . . 377
34.2.1 Importing the Module . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
34.2.2 Connect to the Database . . . . . . . . . . . . . . . . . . . . . . . . . 378
34.2.3 Obtaining the Cursor Object . . . . . . . . . . . . . . . . . . . . . . 379
34.2.4 Using the Cursor Object . . . . . . . . . . . . . . . . . . . . . . . . . 379
34.2.5 Obtaining Information About the Results . . . . . . . . . . . 380
34.2.6 Fetching Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
34.2.7 Close the Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . 381
34.3 Complete PyMySQL Query Example . . . . . . . . . . . . . . . . . . . . . . 381
34.4 Inserting Data to the Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
34.5 Updating Data in the Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
34.6 Deleting Data in the Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
34.7 Creating Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
34.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
34.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387

Part VII Logging


35 Introduction to Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
35.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
35.2 Why Log? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
35.3 What is the Purpose of Logging? . . . . . . . . . . . . . . . . . . . . . . . . . . 392
35.4 What Should You Log? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
35.5 What not to Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
35.6 Why not Just Use Print? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
35.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
36 Logging in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
36.1 The Logging Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
36.2 The Logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
36.3 Controlling the Amount of Information Logged . . . . . . . . . . . . . . 399
36.4 Logger Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
xxiv Contents

36.5 Default Logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402


36.6 Module Level Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
36.7 Logger Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
36.8 Formatters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
36.8.1 Formatting Log Messages . . . . . . . . . . . . . . . . . . . . . . . . 406
36.8.2 Formatting Log Output . . . . . . . . . . . . . . . . . . . . . . . . . . 406
36.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
36.10 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
37 Advanced Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
37.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
37.2 Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
37.2.1 Setting the Root Output Handler . . . . . . . . . . . . . . . . . . 411
37.2.2 Programmatically Setting the Handler . . . . . . . . . . . . . 412
37.2.3 Multiple Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413
37.3 Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
37.4 Logger Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416
37.5 Performance Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
37.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419

Part VIII Concurrency and Parallelism


38 Introduction to Concurrency and Parallelism . . . . . . . . . . . . . . . . . . . . 423
38.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423
38.2 Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423
38.3 Parallelism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
38.4 Distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
38.5 Grid Computing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
38.6 Concurrency and Synchronisation . . . . . . . . . . . . . . . . . . . . . . . . . 428
38.7 Object Orientation and Concurrency . . . . . . . . . . . . . . . . . . . . . . . 428
38.8 Threads V Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429
38.9 Some Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
38.10 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
39 Threading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
39.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
39.2 Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
39.2.1 Thread States . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
39.2.2 Creating a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434
39.2.3 Instantiating the Thread Class . . . . . . . . . . . . . . . . . . . . 435
39.3 The Thread Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436
39.4 The Threading Module Functions . . . . . . . . . . . . . . . . . . . . . . . . . . 438
39.5 Passing Arguments to a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438
39.6 Extending the Thread Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
39.7 Daemon Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
Contents xxv

39.8 Naming Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442


39.9 Thread Local Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442
39.10 Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444
39.11 The Global Interpreter Lock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
39.12 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
39.13 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
40 MultiProcessing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
40.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
40.2 The Process Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
40.3 Working with the Process Class . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
40.4 Alternative Ways to Start a Process . . . . . . . . . . . . . . . . . . . . . . . . 453
40.5 Using a Pool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
40.6 Exchanging Data Between Processes . . . . . . . . . . . . . . . . . . . . . . . 458
40.7 Sharing State Between Processes . . . . . . . . . . . . . . . . . . . . . . . . . . 460
40.7.1 Process Shared Memory . . . . . . . . . . . . . . . . . . . . . . . . . 460
40.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461
40.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462
41 Inter Thread/Process Synchronisation . . . . . . . . . . . . . . . . . . . . . . . . . . . 463
41.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463
41.2 Using a Barrier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463
41.3 Event Signalling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467
41.4 Synchronising Concurrent Code . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
41.5 Python Locks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470
41.6 Python Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
41.7 Python Semaphores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
41.8 The Concurrent Queue Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476
41.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478
41.10 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478
42 Futures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
42.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
42.2 The Need for a Future . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
42.3 Futures in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482
42.3.1 Future Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483
42.3.2 Simple Example Future . . . . . . . . . . . . . . . . . . . . . . . . . . 483
42.4 Running Multiple Futures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485
42.4.1 Waiting for All Futures to Complete . . . . . . . . . . . . . . . 486
42.4.2 Processing Results as Completed . . . . . . . . . . . . . . . . . 488
42.5 Processing Future Results Using a Callback . . . . . . . . . . . . . . . . . 489
42.6 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490
42.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490
xxvi Contents

43 Concurrency with AsyncIO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493


43.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493
43.2 Asynchronous IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493
43.3 Async IO Event Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494
43.4 The Async and Await Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . 495
43.4.1 Using Async and Await . . . . . . . . . . . . . . . . . . . . . . . . . . 496
43.5 Async IO Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
43.6 Running Multiple Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500
43.6.1 Collating Results from Multiple Tasks . . . . . . . . . . . . . 500
43.6.2 Handling Task Results as They Are Made
Available . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501
43.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
43.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
44 Performance Monitoring and Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . 505
44.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505
44.2 Why Monitor Performance and Memory? . . . . . . . . . . . . . . . . . . . 505
44.3 Performance Monitoring and Profiling . . . . . . . . . . . . . . . . . . . . . 506
44.4 Performance Monitoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507
44.4.1 The Time Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507
44.4.2 The Timeit Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
44.4.3 The Psutil Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
44.5 Python Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
44.5.1 The cProfile Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
44.5.2 The Line_Profiler Module . . . . . . . . . . . . . . . . . . . . . . . 511
44.5.3 The Memory_Profiler Module . . . . . . . . . . . . . . . . . . . . 512
44.5.4 Additional Third-Party Libraries . . . . . . . . . . . . . . . . . . 512
44.6 Profiling with cProfile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 512
44.7 Memory Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
44.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517

Part IX Reactive Programming


45 Reactive Programming Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
45.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
45.2 What Is a Reactive Application? . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
45.3 The ReactiveX Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522
45.4 The Observer Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522
45.5 Hot and Cold Observables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
45.6 Differences Between Event Driven Programming
and Reactive Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524
45.7 Advantages of Reactive Programming . . . . . . . . . . . . . . . . . . . . . . 525
45.8 Disadvantages of Reactive Programming . . . . . . . . . . . . . . . . . . . 525
45.9 The RxPy Reactive Programming Framework . . . . . . . . . . . . . . . 526
45.10 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526
Contents xxvii

46 RxPy Observables, Observers and Subjects . . . . . . . . . . . . . . . . . . . . . . 527


46.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527
46.2 RxPy Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527
46.3 Observables in RxPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527
46.4 Observers in RxPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 528
46.5 Multiple Subscribers/Observers . . . . . . . . . . . . . . . . . . . . . . . . . . . 530
46.6 Subjects in RxPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531
46.7 Observer Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534
46.7.1 Available Schedulers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
46.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
46.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
47 RxPy Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
47.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
47.2 Reactive Programming Operators . . . . . . . . . . . . . . . . . . . . . . . . . . 537
47.3 Piping Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538
47.4 Creational Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539
47.5 Transformational Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539
47.6 Combinatorial Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
47.7 Filtering Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
47.8 Mathematical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
47.9 Chaining Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
47.10 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546
47.11 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546

Part X Network Programming


48 Introduction to Sockets and Web Services . . . . . . . . . . . . . . . . . . . . . . . 551
48.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
48.2 Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
48.3 Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 552
48.4 Addressing Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 552
48.5 Localhost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553
48.6 Port Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554
48.7 IPv4 Versus IPv6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 555
48.8 Sockets and Web Services in Python . . . . . . . . . . . . . . . . . . . . . . . 555
48.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 556
49 Sockets in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557
49.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557
49.2 Socket to Socket Communication . . . . . . . . . . . . . . . . . . . . . . . . . . 557
49.3 Setting up a Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558
49.4 An Example Client Server Application . . . . . . . . . . . . . . . . . . . . . 558
49.4.1 The System Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . 558
49.4.2 Implementing the Server Application . . . . . . . . . . . . . . 559
xxviii Contents

49.4.3 Socket Types and Domains . . . . . . . . . . . . . . . . . . . . . . . 560


49.4.4 Implementing the Client Application . . . . . . . . . . . . . . 561
49.5 The Socketserver Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 562
49.6 Http Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565
49.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567
49.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 568
50 Web Services in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571
50.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571
50.2 RESTful Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571
50.3 A RESTful API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572
50.4 Python Web Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573
50.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574
51 Flask Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575
51.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575
51.2 Flask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575
51.3 Hello World in Flask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
51.3.1 Using JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
51.4 Implementing a Flask Web Service . . . . . . . . . . . . . . . . . . . . . . . . 577
51.4.1 A Simple Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577
51.4.2 Providing Routing Information . . . . . . . . . . . . . . . . . . . 577
51.5 Running the Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578
51.6 Invoking the RESTFul Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579
51.6.1 The Final Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580
51.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580
52 Flask Bookshop Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583
52.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583
52.2 Building a Flask Bookshop Service . . . . . . . . . . . . . . . . . . . . . . . . 583
52.3 The Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583
52.4 The Domain Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
52.5 Encoding Books into JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586
52.6 Setting Up the GET Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588
52.7 Deleting a Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 589
52.8 Adding a New Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590
52.9 Updating a Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592
52.10 What Happens if We Get It Wrong? . . . . . . . . . . . . . . . . . . . . . . . . 593
52.11 Bookshop Services Listing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594
52.12 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596

Part XI Data Science: Data Analytics and Machine Learning


53 Introduction to Data Science . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
53.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
53.2 Data Science . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
53.3 Data Science Tools and Techniques . . . . . . . . . . . . . . . . . . . . . . . . 602
Contents xxix

53.4 Data Analytics Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604


53.5 Python and Data Science . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 606
53.6 Machine Learning for Data Science . . . . . . . . . . . . . . . . . . . . . . . . 607
53.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608
54 Pandas and Data Analytics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611
54.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611
54.2 The Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611
54.2.1 The UK Government COVID Data Set . . . . . . . . . . . . . 611
54.2.2 The Google Mobility Data Set . . . . . . . . . . . . . . . . . . . . 613
54.3 Python Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614
54.3.1 Pandas Series and DataFrames . . . . . . . . . . . . . . . . . . . . 615
54.4 Loading and Analysing UK COVID Data Set . . . . . . . . . . . . . . . . 616
54.5 Loading the Google Mobility Data Set . . . . . . . . . . . . . . . . . . . . . 621
54.6 Merging Two DataFrames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 622
54.7 Analysing the Combined Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623
54.8 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627
55 Alternatives to Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
55.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
55.2 Comparing Pandas 2.0.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
55.3 Pandas 1.x v 2.x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
55.4 Pandas Versus Other Libraries and Tools . . . . . . . . . . . . . . . . . . . . 630
55.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 632
56 Machine Learning in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
56.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
56.2 The Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
56.3 SciKitLearn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634
56.4 The Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635
56.5 Using Regression Supervised Learning Systems . . . . . . . . . . . . . 636
56.6 K-Nearest Neighbour Regressor . . . . . . . . . . . . . . . . . . . . . . . . . . . 636
56.7 Decision Tree Regressor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 638
56.8 Random Forest Regressor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639
56.9 Summary of Metrics Obtained . . . . . . . . . . . . . . . . . . . . . . . . . . . . 640
56.10 Creating the Regressor Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 640
56.11 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 642
57 Pip and Conda Virtual Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . 643
57.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643
57.2 Virtual Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643
57.3 Working with Pip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 644
57.3.1 Activating a Pip Environment . . . . . . . . . . . . . . . . . . . . 644
57.3.2 Installing Modules Using Pip . . . . . . . . . . . . . . . . . . . . . 645
57.3.3 Deactivating a Pip Environment . . . . . . . . . . . . . . . . . . 646
57.3.4 Check Version of Pip . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646
57.3.5 Installing Modules into a Pip Environment . . . . . . . . . 646
xxx Contents

57.3.6 Freezing Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 647


57.4 Conda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 648
57.5 Anaconda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649
57.5.1 Installing Anaconda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649
57.6 Working with Anaconda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651
57.6.1 Checking the Conda Version . . . . . . . . . . . . . . . . . . . . . 651
57.6.2 Updating Conda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651
57.6.3 Creating a Conda Environment . . . . . . . . . . . . . . . . . . . 652
57.6.4 Listing Available Conda Environments . . . . . . . . . . . . 653
57.6.5 Activating a Conda Environment . . . . . . . . . . . . . . . . . . 654
57.6.6 Deactivating a Conda Environment . . . . . . . . . . . . . . . . 655
57.6.7 Listing the Modules Loaded into a Conda
Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655
57.6.8 Removing an Anaconda Environment . . . . . . . . . . . . . 656
57.6.9 Installing a Module into a Conda Environment . . . . . . 656
57.7 Anaconda in PyCharm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 658
57.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 658
Chapter 1
Introduction

1.1 Introduction

I have heard many people over the years say that Python is an easy language to learn
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
eleven different topics:
1. Advanced Language Features. The first section in the book covers topics
that are often missed out from introductory Python books such as slots, weak
references __init__() versus __new__() and metaclasses.
2. Computer Graphics. The book covers Computer Graphics and Computer
Generated Art in Python as well as graphical user interfaces and graphing/
charting via Matplotlib.
3. Games Programming. This topic is covered using the pygame library.
4. Testing and Mocking. Testing is an important aspect of any software develop-
ment; this book introduces testing in general and the PyTest module in detail.
It also considers mocking within testing including what and when to mock.

© Springer Nature Switzerland AG 2023 1


J. Hunt, Advanced Guide to Python 3 Programming,
Undergraduate Topics in Computer Science,
https://doi.org/10.1007/978-3-031-40336-1_1
Exploring the Variety of Random
Documents with Different Content
inkább magamnak tarthattam volna meg; azonban pedig az, a mit
felőle veled jószivüleg közlöttem, legalább bizonysága lesz azon jó
szándékomnak, melylyel neked tetszeni kivántam, és az által, hogy
kölcsönös szerencsénket alapitám, nálad jó emlékezetben
maradhassanak. Én tehát neked egy igazságosabb és helyesebb
ajánlást teszek, s magad lássad, fog-e neked tetszeni? Te mondád –
folytatá a barát, – hogy nyolczvan tevéd van. Én tehát kész vagyok
téged a kincshez vezetni s ott veled annyi aranyat és drágaköveket
rakni reájuk, a mennyit csak elbirnak, azon föltétel alatt, ha illendően
megrakodtunk, te nekem tevéid felét a rajtok levő kincscsel együtt
átengeded, s magadnak csak a másik felét tartod vissza, mire azután
elválunk, ugy hogy mindenik oda vezethesse tevéit, a hova neki
tetszik. Látod, hogy ezen osztozás egészen megegyezik az
illendőséggel, s ha nekem negyven tevét ajándékozol, tőlem helyette
annyit kapsz, hogy azon magadnak ezer más tevét is vehetsz.“
Nem tagadhatám, hogy a barátnak ajánlása igen igazságos.
Azonban anélkül, hogy gondolkodtam volna azon temérdek
kincsekről, melyek nekem ezen egyezésnél fogva juthattak, tevéim
felének átengedését nagy veszteségként néztem, kivált ha
meggondolám, hogy a barát szintoly gazdag leend, mint én. Elég
ahhoz, én máig is háládatlansággal köszönék meg egy önkényt való
jótéteményt, melyet azontul a baráttól még nem is kaptam volt. Itt
azonban nem sok idő maradt a tanakodásra. Vagy el kelle fogadnom
az ajánlatot, vagy elkészülnöm egy holtom napjáig tartó bánkodásra
amiatt, hogy magam hibája által szalaszték el egy alkalmat, melynél
tetemesen meggazdagodhattam volna.
Én tehát azonnal összehajtám tevéimet, s igy megindulánk.
Minekutána igy haladtunk egy darabig, egy igen bő völgyhöz értünk,
melynek bejárása azonban igen szük és keskeny vala. Tevéim csak
egyenkint mehettek rajta keresztül, s a mint tágult a vidék, ugy lett
ismét lehetségessé, hogy a legjobb rendben haladhassanak. A két
hegy, mely a völgyet képezé s hátul félkörösen zárá, egyébiránt oly
magas, meredek és járhatlan vala, hogy nem kellett attól tartanunk,
hogy ott valamely halandó megláthasson.
Midőn megérkeztünk a két hegy közé, szól hozzám a barát: „Most
ne menjünk már tovább; állitsd meg tevéidet s fektesd azokat álló
helyükön hasra, hogy fáradság nélkül megterhelhessük, s ha ezt
megtevéd, a kincs felnyitásához fogok.
Megtévén azt, a mit a barát mondott, magam is utána menék.
Csiholó szerszámmal egyik kezében, egy kevés száraz gallyat
szedegetett össze, hogy tüzet rakhasson. Mihelyt ez égett, egy kevés
tömjénfélét hinte bele, néhány szavakat mormogva hozzá, melyeket
én nem érték. Azonnal sürü füst kerekedett fel belőle. Ő ezen füstöt
elosztá, s ekkor a sziklában, mely a két hegy között meredeken igen
magasra felnyult, noha abban semminemü nyilásnak még csak
nyoma se látszott, egyszerre mégis igen nagy támadt, mely
kapuforma volt két kapuszárnynyal s csodálatos mesterséggel volt a
sziklába készitve.
Ezen nyiláson át egy, a sziklába vágott nagy térségben gyönyörü
palotát szemlélénk, mely inkább valami lelkek, mint emberi kezek
munkaművének tetszett lenni, mert nem is látszott lehetségesnek,
hogy emberek ily merész és csodálnivaló dologra csak gondolatban
is vetemedhettek volna.
Azonban, oh igazhitüek uralkodója, ezen észrevételt csak most
teszem még felséged előtt, és nem tettem akkor mindjárt. Sőt azon
mérhetetlen gazdagságokat sem csudáltam, melyek ott mindenfelől
szemeimbe ötlöttek, hanem anélkül, hogy ezen temérdek kincsek
czélirányos elosztásán elmélkedtem volna, hanem valamint a prédára
lecsapó sas, az előttem levő legelső rakás aranynak estem, s abból,
egy épen felkapott zsákba annyit kezdettem rakni, a mennyit csak
elbirhatni véltem. – A zsákok igen nagyok valának, s én szerettem
volna egészen megtölteni, azonban mégis kénytelen voltam tevéim
erejével néminemü arányba hozni.
A barát szintugy tett, mint én; azonban észrevevém, hogy inkább
a drágakövek után kapkodott, s midőn nekem annak okát
megmondotta, követém példáját, s mi sokkal több drágaköveket
vittünk magunkkal, mint vert aranyat. Végre minden zsákunkat tele
töltők, s felrakók tevéinkre, miután nem volt egyéb hátra, mint a
kincset bezárni, s elindulni.
Minekelőtte elindulánk, még egyszer bement a barát a kincshez,
s minthogy abban több, aranyból s más drága anyagokból
mesterségesen készült edények valának, észrevevém, hogy ezen
edények egyikéből kivett egy kis, előttem ismeretlen fából készült
szelenczét, s keblébe dugta, minekutána nekem megmutatta, hogy
abban csak valami hajkenőcs féle van.
A barát annakutána ismétlé a felnyitáskor tett szertartásait, s
minekutána bizonyos szavakat mondott volna, ismét bétevődött a
kincstár, s a szikla ugy álla előttünk, mint azelőtt.
Erre tevéinket fel hagyánk kelni, s felosztánk magunk között. Én
azon negyven elébe állottam, melyet magamnak kiválasztottam, a
barát pedig azon többi elébe, melyet neki által engedtem.
Ezután ismét kimenénk a szorulaton, melyen bejövénk, s igy
ballagánk egymással a nagy országutig, hol el akaránk válni, a barát
t. i. hogy Balsora felé folytassa utját, magam pedig, hogy haza térjek
Bagdádba. Hogy megköszönhessem ily nagy jótéteményét, a
leghathatósabb kifejezésekkel, s hálálkodásom legbuzgóbb
fogadásaival éltem, hogy engem választott minden többi halandó
közül ki, e temérdek kincsekben való részesitésre. Erre igen szivesen
megölelkezénk, s minekutána egymásnak minden jókat kivántunk,
mindegyik utjának indult.
Alig haladtam nehány lépésnyire, hogy tevéimet, melyek azalatt
kimutatott utjokon előre haladtak, ismét elérhessem, midőn a
háládatlanság és irigység rosz lelke keblembe fészkelődött.
Töprenkedtem elvesztett negyven tevémen, de még inkább a rajtok
lévő gazdagságon. „A barátnak,“ igy gondolkodám, „mind ezen
drágaságokra nincsen szüksége; hiszen ő tetszése szerint
parancsolhat az egész kincscsel, s abból annyit vehet, a mennyit
akar.“ Én tehát a legfeketébb háladatlanságot forralva, egyszerre
eltökélém magamban, hogy tevéit terhestül elszedem.
Tervem végrehajtása végett legelőbb megállitám tevéimet, s
azután a barát után szaladtam, kinek egész erőmből utána kiálték,
mintha még valami mondandóm volna neki; egyuttal jegyek által
értésére adám, hogy ő is állitsa meg tevéit, s várjon rám. Meghallá
kiáltásomat, s megálla.
Midőn utólértem, mondám neki: „Atyámfia! alig hagytalak el,
midőn meggondolék valamit, mi előbb eszembe nem jutott, s miről
talán magad sem gondolkodtál azelőtt. Te igen jó barát vagy, s egy
csendes, minden földi gondoktól s egyéb foglalatosságoktól, azt
kivéve, hogy istennek szolgálj, szabad élethez vagy szokva. Te
bizonynyal nem fogod tudni, mily terhet vállaltál magadra, midőn
általvettél ily számos tevét. Ha fogadnád tanácsomat, csak
harminczat vinnél el magaddal, s vélekedésem szerint még ezeknek
vezetésével is elég bajod lesz. E tekintetből bizhatol bennem, mert
nekem e dologban van tapasztalásom.
„Úgy vélem, igazságod van“ mond a barát, ki látá, hogy nem igen
tagadhat meg tőlem valamit, „s megvallom,“ folytatá, hogy erről
valóban nem gondolkodtam. Arról, a mit itt mondasz, már valóban
nyugtalankodni is kezdtem. Azért válaszsz magadnak ki közülök tizet,
s vezesd el Isten nevében.“
Én tehát kiválaszték tizet, megtéritém s többi tevém után
eresztém. Valóban nem hittem, hogy a barátot ily könnyen
rábeszélhetem; ez telhetetlenségemet még inkább öregbité, s
kecsegtetém magamat, hogy talán baj nélkül kaphatok tőle még
tizet.
A helyett tehát, hogy a gazdag ajándékot, melyet épen ada,
megköszöntem volna, igy szólottam hozzá tovább: „Atyámfia! azon
részvételnél fogva, melylyel viseltetem nyugodalmad iránt, meg nem
válhatom tőled, hogy figyelmessé ne tegyelek annak isméti
megfontolására, mi bajos harmincz tevével bánni, kivált oly
embernek, mint te, ki az ilyeshez épen nem szoktál. Sokkal
nyugodalmasabb lehetnél, ha engem még egyszer megajándékoznál
ugy, mint csak az imént. Én neked ezt, mint könnyen általláthatod,
nem annyira magam s önhasznom miatt, mint inkább a végre
cselekszem, hogy ez által neked nagyobb örömet szerezzek.
Könnyitsd meg tehát terhedet még tiz tevével, s add által azokat is
nekem, mint oly embernek, ki szintoly könnyen bánik száz tevével,
mint egygyel.“
Beszédem kivánt foganatu volt, s a barát minden vonakodás
nélkül általengedé a tiz tevét, melyet ujra kivántam tőle, ugy, hogy
neki nem maradt már több, csak husz. Én tehát hatvan tevének
birtokában voltam, melyek terhének értéke jóval felülmulta sok
fejedelem gazdagságáét, s igy azt lehetne gondolni, hogy igy végre
meg kellett lennem elégedve.
Azonban, oh igazhitüek uralkodója! valamint a vizkórságos, ki
minél többet iszik, annálinkább szomjazik, még hevesebben
vágyakodtam, hogy a barátnak maradt husz tevét is magamévá
tegyem.
Megkettőztetém tehát buzgó kérésemet, esedezésemet és
sürgetésemet, a barátot arra venni, hogy a huszból még tizet adjon,
s ő végre hajolt kérésemre. A mi a még nála levő tiz tevét illeti,
ezekért megölelém, megcsókolám, s szentül kérém, hogy meg ne
tagadja tőlem, s azáltal azon örökös kötelezettségeknek, melyekkel
iránta viseltetem, tegye fel a koronát, hogy végre azon
nyilatkoztatásával, hogy mindenre rá áll, örömömet teljesité.
„Jó hasznát vedd azonban atyámfia! – mond ő – s emlékezzél
meg arról mindig, hogy az Isten szintoly könnyen elveheti tőlünk a
gazdagságokat, a mint azokat adta, ha nem forditjuk szegények
gyámolitására, kiket ő csak azért hágy szükségben, hogy a
gazdagoknak alkalmuk legyen, alamizsnáik által nagyobb érdemeket
szerezni ama világra.“
Elvakultságom oly nagy volt, hogy nem voltam képes ily
üdvösséges tanácsot követni. Sőt meg sem elégedtem azzal, hogy
magamat nyolczvan tevéim birtokában lenni láttam s tudtam, hogy
oly kincscsel vannak megterhelve, melylyel nekem a legboldogabb
emberré kellett lennem; hanem eszembe jutott, hogy az a kis
szelencze kenőcs, melyet a barát magához vett, s nekem
megmutatott, valami sokkal nagyobb értékü lehet, mint mindazon
kincsek, melyeket neki köszönheték.
„A hely, honnan a barát elvevé,“ igy okoskodám magamban, „s
azon nyugtalanság, melylyel annak birtokába jutni törekedék,
gyanitatja velem, hogy az valami rejtélyest foglal magában.“
Ez engem annak megnyerése végett következőre indíta. Csak
épen imént ölelém meg s búcsuztam el tőle. Azonban még egyszer
feléje fordulék, s mondám neki: „Még egyet, mitevő leszsz ama kis
kenőcs szelenczével? Oly csekély becsűnek látszik előttem,“
folytatám, „hogy nem is érdemes arra, hogy magaddal vigyed; kérlek
tehát, ajándékozd nekem. Hiszen általában véve egy barátnak, mint
te, ki a világ hiuságairól egészen lemondott, ugy sem kell
hajkenőcs.“
Adta volna az Isten, hogy ezen szelenczét megtagadta volna
tőlem! Azonban, ha tenni akarta volna is, már nem lettem volna
eléggé eszemen, s azontul erősebb is voltam nálánál, s erősen
eltökélve, annak magam részére erővel való megszerzésére is, hogy
meg legyek nyugtatva a felől, nehogy valaki mondhassa, hogy ama
csak legkevesebbet is kapott a kincsből, – bármennyi
háládatossággal tartoztam is neki.
A barát azonban, a helyett, hogy megtagadta volna tőlem,
azonnal kihuzá kebléből, s a legnagyobb illendőséggel általadá
nekem, mondván: „Itt van, atyámfia, nehogy még ez az egy is
hibázzék teljes megelégedésedből. Ha szolgálhatok még más
valamivel, csak mondd meg, én kész vagyok annak teljesitésére.“
Midőn a szelencze kezeimben volt, kinyitám, megtekintém a
kenőcsöt, s mondám hozzá: „Minthogy oly jószivü vagy, hogy ki sem
fáradsz az irántam való szivességekben, mondd meg kérlek, mi
különös hasznát vehetni ezen kenőcsnek?“
„Az felettébb emlékezetre méltó és csudálatos“ mond a barát.
„Ha t. i. abból egy keveset a bal szemedre és szempilládra kensz,
szemeid elébe tünnek minden kincsek, melyek a föld kebelében
rejtekeznek; ha pedig jobb szemedre kensz valamit belőle,
megvakulsz.“
E csudálatos foganatot magamon kivántam tapasztalni, s ezért,
kezébe adván a szelenczét, mondám a barátnak: „Nesze, s kenj egy
keveset a kenőcsből bal szememre; te ahhoz jobban értesz mint én.
Égek azon kivánságtól, azt magamon tapasztalni, a mi nekem
hihetetlennek tetszik.“
A barát kész vala e fáradságra. Be kelle hunynom bal szememet,
s ő rá kene egy keveset a kenőcsből. Ez meglevén, kinyitám
szememet, s látám, hogy igazat mondott. Én valósággal temérdek
számu kincstárakat szemlélék meg, melyek oly temérdek és
számtalanféle kincsekkel valának megtelve, hogy lehetetlenség
lenne, azokat mind egyenkint előadnom. Mivel azonban jobb
szememet kézzel erősen be kelle fognom, s én ezt eluntam,
megkérém a barátot, hogy ezen kenőcsből a jobb szememre is
kenjen egy keveset.
„Azt is megteszem ugyan,“ mond a barát, „azonban nem szabad
megfelejtkezned arról, a mit csak az imént mondtam, hogy mihelyt
csak egy keveset tészsz belőle jobb szemedre, azonnal megvakulsz
tőle. A kenőcsnek már egyszer meg van ezen ereje, s ehhez kell
magadat tartanod.“
A helyett, hogy elhittem volna, hogy a barát igazat szól, inkább
azt képzeltem magamban, hogy alatta még más titok is lappang,
melyet nem akar velem tudatni.
„Atyámfia“ mondám hozzá, „jól látom, hogy el akarsz ámitani;
hiszen természet ellen való volna, ha egy és ugyanazon kenőcs két
épen ellenkező foganatot szülne.“
„S mégis egészen ugy van a dolog, a mint neked mondom,“ felel
a barát, az Isten nevét hiva tanubizonyságul, „s elhiheted szavamra,
mert én az igazságot sohasem vagyok képes eltagadni.“
Én a barát szavának, ki velem mint becsületes ember szólott,
nem akarék hinni; azon telhetetlen kivánás, hogy a föld minden
kincseit öntetszésem szerint nézhessem, s azokkal talán,
valahányszor kedvem telnék, élhessek, azt tevé, hogy sem nem
hallgattam óvó intéseire, sem pedig egy dolgot el nem akarék hinni,
mely – mint nemsokára azután legnagyobb szerencsétlenségemre
tapasztalám, – csak igen is igaz volt.
Belém fészkelt előitéletemben azt hitetém el magammal, hogy
ezen kenőcs, ha bal szemre kenve oly erejü, hogy a föld minden
kincseit láttatja, jobb szemen használva talán azon erővel bir, hogy
azokkal azonnal kivánságom szerint parancsolhatok. Ezen
gondolatomban erősködve unszolám a barátot, hogy kenjen valamit
a jobb szememre; ő azonban állhatatosan vonakodék annak
teljesitésétől.
„Minekutána ennyi jót tettem veled atyámfia, mond ő hozzám,
„rá nem vehetem magamat, hogy neked ily szörnyü
boldogtalanságot okozzak. Fontold meg magad, mily
szerencsétlenség a szeme világától megfosztva lenni, s ne helyezz
azon szomoru kénytelenségbe, hogy oly dologban tegyek eleget
kivánságodnak, melyet holtod napjáig siratnál.“
Én megátalkodásomban végsőre vetemedtem. „Atyámfia,
mondám hozzá eléggé kemény hangon, kérlek, hagyj fel mindazon
nehézségekkel, melyeket itt teszesz nekem; te nekem nagylelküleg
megtettél mindent, a mit tőled addig kértem, azt akarod most, hogy
ily szembe sem tünő csekélység miatt megelégedetlenül váljam el
tőled? Isten nevében, tedd meg ezen utolsó kegyességet is velem.
Akármi legyen is következése, soha sem foglak okolni, hanem annak
oka mindig rám fog háramlani“
A barát minden lehetséges módon próbált ellentállani, de midőn
látná, hogy képes volnék rajta erőt venni, mondá: „Minthogy már
épen okvetetlenül akarod, megteszem kivánságodat.“
Ekkor vett egy keveset ezen veszélythozó kenőcsből, s a jobb
szememre kente, melyet erősen behunytam. De fájdalom, midőn
ismét felnyitám, nem láttam szemem előtt egyebet sürű setétségnél,
s én folyvást vak maradtam, a mint látod.
„Oh szerencsétlen barát.“ Kiálték azonnal, „a mit mondottál, csak
igen is igaz! Boldogtalan kiváncsiság“ tevém hozzá, „telhetetlen
gazdagságok után való vágyakodás, a szerencsétlenségnek mily
örvényébe döntöttetek engem! Érzem ugyan, hogy ezt mind magam
okoztam magamnak; azonban, kedves atyámfia“ szólék a barát felé
fordulva, „ki te oly adakozó és jól tévő vagy, nincsen annyi csudatévő
titkaid között egy is, mely nekem szemeim világát ismét visszaadná?“
„Boldogtalan“ felel nekem erre a barát, „hogy ezen
szerencsétlenséget el nem kerülted, bizonyára nem hibám; neked
azonban most csak az jutott, a mit megérdemlettél, s szived vaksága
tested világtalanságát okozta. Igaz, hogy birok titkokkal; ezt te azon
rövid idő alatt, hogy együtt vagyunk, könnyen észrevehetted;
azonban egyet sem ismerek, mely szemed világát ismét
visszaadhatná. Ha gondolod, hogy van még egy olyan is, folyamodjál
az Istenhez; csak ő adhatja neked azt ismét vissza. Ő neked oly
kincseket adott, melyekre nem valál érdemes; ő azoktól most ismét
megfoszta, s általam oly emberekre juttatja, kik nem lesznek oly
háládatlanok mint te.“
A barát egy szót sem szóla többé, s én sem birtam neki felelni
egy szót is. Ő most zavarodásomban, s egy leirhatatlan mély
fájdalomba merülten elhagya, s minekutána nyolczvan tevémet
összegyüjté, maga előtt hajtá azokat, s folytatá utját Balsora felé.
Rimánkodám neki, hogy ne hagyna el ezen szerencsétlen
állapotomban, s vezetne legalább a legelső karavánig; de ő siket
marada kéréseim s jajgatásaim iránt. Ily móddal megfosztva
szemeim világától, s mindentől, a mivel e világon birtam, éhség és
szomoruság miatt meghaltam volna, ha egy karaván, mely
Balsorából jött, fel nem vett s Bagdádba nem vitt volna.
Oly helyzetből, mely, ha mindjárt nem hatalomra s erőre is, de
legalább gazdagságra s fényre nézve, engem fejedelmek sorába
állita, egyszerre gyám nélkül látám magamat koldusbotra jutni.
Kénytelen valék alamizsnáért esedezni, a mit eddig tettem is; de
hogy Isten ellen való vétkemért lakoljak, egyuttal azon büntetést is
szabtam magamnak, hogy minden jóltevőtől, ki könyörül
nyomoruságomon, egy pofoncsapást kapjak.
Ez az oka, oh igazhitüek uralkodója! ama magamviseletének,
mely felséged előtt tegnap oly különösnek tetszett, s rám talán
haragját is háritotta. Bocsánatot kérek még egyszer, mint
rabszolgája, és szivesen alája vetem magamat minden büntetésnek,
melyet megérdemlettem. Ha azonban felségednek tetszenék,
bünbánatomról itéletet hozni, meg vagyok róla győződve, hogy igen
csekélynek s messze bünöm alatt lévőnek fogja felséged találni.
Minekutána elbeszélte a világtalan történeteit, mondá a chalyf
hozzá: „Baba Abdallah, bünöd nagy; azonban, hála az Istennek,
hogy általláttad annak nagyságát, s magadra azért ezen nyilvános
elégtételt szabtad. Ez már most elég: azután magadban gyakorold
ezen bünbánásodat; s el ne mulaszd semmi imádságodban, melyet
hitbeli kötelességből teszesz mindennap, hogy őtet bocsánatért kérd;
s hogy ettől életed fentartásáról való gondoskodásod el ne vonjon,
egész életedre kiszabok egy alamizsnát, melyet neked nagyvezérem
kiadatand. Azért el ne távozzál, s várakozzál, mig parancsom
teljesité.“
Ezen szavaknál leborult Baba Abdallah az uralkodó fejedelmi
széke előtt, s felkelvén, minden kigondolható szerencsét s
boldogságot kivánt neki.
Harun Arresyd chalyf, megelégedve Baba Abdallah és a barát
történetével, a fiatal ember felé fordult, kit kanczájával láta oly
roszul bánni, s szintugy megkérdezte tőle nevét, mint a vaktól. A
fiatal ember mondá neki, hogy neve Sidi Numan.
„Sidi Numan“ mond erre a chalyf hozzá „én életemben már sok
lovat láttam nyereg alá szoktatni, s magam is szoktattam már, de
még egyet sem oly kegyetlenül ütni verni, mint te tegnap az utczán,
s minden nézők botránkoztatására, kik a miatt hallhatólag morogtak,
bántál kanczáddal. Én szintugy megbotránkozám rajta, mint a
körülállók, s nem sok hibázott, hogy – egészen egyébiránti szokásom
ellenére – ki nem nyilatkoztatám magamat, pajkosságod
félbeszakasztatására. Mindamellett is külsőd nem mutat kegyetlen s
durva emberre. Sőt kész vagyok elhinni, hogy nem épen ok nélkül
bántál vele igy. Minthogy tudom, hogy ez nem volt először, s te már
hosszabb idő óta naponkint kinozod igy kanczádat, szeretném annak
okát megtudni, s azért idéztelek előmbe, hogy azt tőled megtudjam.
Fedezd fel azért előttem a dolgot egész mivoltában, s ne titkolj el
tőlem semmit is.“
Sidi Numan könnyen elértette, mit kiván tőle a chalyf; de ennek
teljesitése őt a legkinosb zavarodásba ejté. Több izben változott
szine, s akaratja ellen látszott belőle a zürzavar, melyben volt.
Mindamellett meg kellett vallani az okát. Ezért, minekelőtte
megszólamlék, leborula a chalyf fejedelmi széke előtt, s midőn ismét
felkele, beszédhez akara fogni, hogy kielégitse a chalyf ujságvágyát;
mindazáltal zavarodva hallgatott, nem annyira a chalyfnak, ki előtt
megjelent, dicsősége, mint inkább teendő elbeszélése tartalmától
rettenve meg.
Bármi nyughatatlanul várta is különben a chalyf akaratja
teljesitését, még sem mutatott haragot Sidi Numan hallgatásáért;
mert azt vélé, hogy talán nincs elegendő bátorsága, előtte szólani
vagy hogy beszédének azon hangjától, melylyel megszólitá, szeppent
meg, vagy hogy végre abban, a mit elő kelle beszélnie, oly dolgok
fordulnának elő, melyeket inkább el szeretne hallgatni.
„Sidi Numan“ monda hozzá a chalyf bátoritására, „szedd össze
magad, s képzeld ugy a dolgot, mintha azt, a mit kivántam, nem
nekem, hanem valamelyik barátodnak, ki arra megkérne, kellene
elbeszélned. Ha egyébiránt e történetben olyas valami foglaltatnék, a
mi neked zavart okoz, vagy melyről gondolod, hogy engem
megbánthatna, azt előre megbocsátom. Azért tehát ne
nyugtalankodjál, beszélj bizvást, s el ne titkolj előttem semmit is,
épen ugy, mintha legjobb barátodat szemlélnéd magad előtt.“
Sidi Numan, kit a chalyf utolsó szavai megnyugtatának, végre
megszólamlott, mondván: „Igazhitüek uralkodója, bármi nagy légyen
is a zavarodás, melybe felséged közelében, s fejedelmi széke fénye
előtt esik minden halandó, mégis sokkal erősebbnek érzem
magamat, hogy sem elhinném, hogy ezen tisztelő félelem annyira el
birna némitani, hogy a felségednek tartozó engedelmesség ellen
vétsek, vagy abban, mit tőlem kivánna, tudósitással szolgálni ne
tudnék. Ha nem merem is magam legtökéletesb embernek állitani,
még sem vagyok viszont oly roszakaratu, hogy csak valaha is
eszembe jutott volna legkisebb olyas valamit a törvények ellen
cselekedni, a mi bennem félelmet gerjeszthetett volna ezeknek
kemény büntetésöktől. Azonban, bármi jó volt is akaratom,
elismerem mégis, hogy nem voltam ment tudatlanságból elkövetett
hibáktól. Ez az én esetem. Mindamellett nem mondom, hogy a
felségedtől még meghallgattatásom előtt nyert kegyes
bocsánatjában bizom; hanem inkább meghajlom felséged igazságos
itélete, sőt büntetése alá is, ha megérdemlettem. Megvallom, hogy
kanczámmal egy idő ótai bánásom furcsa, kegyetlen s nem
követnivaló, de reménylem, hogy okát igen helyesnek, engem pedig
inkább szánakodásra, mint büntetésre méltónak fog itélni. Azonban
nem illik unalmas előbeszéddel felségedet tovább is függőben
tartanom, a miért is ime történetem.“

Sidi Numan története.


„Igazhitüek uralkodója,“ folytatá Sidi Numan, származásomat
elhagyom, mert az nem oly fénylő, hogy érdemes volna az emlitésre.
A mi a szerencse javait illeti, elődeim jó gazdálkodásukkal hagytak
reám annyit, a mennyit csak kivánhattam, hogy abból becsületes
ember módjára fenhéjázás nélkül és másnak terhére nem esve,
élhessek.
Ily körülmények között szerencsém befejezésére nem
kivánhattam már egyebet, mint oly szeretetre méltó házaspárt
lelhetni, ki engem szintoly hűszivüleg és gyengéden szeretne viszont,
mint én őtet. Az Istennek azonban nem tetszett engem olyannal
ajándékozni meg; hanem inkább olyat ada, ki összekelésünk első
napjától kezdé türelmességemet oly próbákra tenni, melyeket csak
azok képzelhetik el, kik hasonlókat valának kénytelenek szenvedni.
Minthogy honunk szokásai szerint minden házasságok ugy
szerződnek, hogy azt, kivel összekelünk, azelőtt sem látjuk, sem
ismerjük, tudva lesz felséged előtt, hogy nincs oka panaszkodásra
egy férjnek is, csak ijesztő csunya, vagy idétlen alaku ne legyen
elvett neje, s jó erkölcsei, esze, módos magaviselete, testének
netaláni apróbb hibáit ismét felüssék.
Midőn nőmet legelébb látám fátyola nélkül, – akkor t. i. midőn a
szokott szertartások után épen házamhoz hozatot, – örültem, hogy
szépségéről tett magasztalásokban meg nem csaltak; egészen
izlésem szerintinek találtam, s ő nekem tetszett.
Összekelésünk utáni napon több tál ételből álló ebédet adtak az
asztalra. Az ebédlőbe menék, hol nem találván nőmet, hivatám. Sok
ideig hagyván magát várni, végre előjött. Én nyugtalanságomat
elpalástolám, s igy asztalhoz ülénk.
Én legelébb a rizsből evém, melyet szokásként kanállal vevék ki.
Nőm ellenben, kanál helyett, zsebében hordozott kis evőeszközből,
egy fülvakaró kalánformát veve elő, melylyel kezde a rizsből kivenni,
s azt szemenként, – mert több rá sem fért – szájába kezdé rakni.
Ily evésmódon elbámulva, mondám hozzá: „Amine – mert ez volt
neve – szüleid házánál igy tanultad enni a rizst? Azért teszed talán,
mivel nem vagy nagyehető, vagy szemenként akarod megszámlálni,
hogy egyszer ne egyél többet mint másszor, ha csupa
takarékosságból teszed, hogy tékozlóvá ne legyek, bizonyossá
teszlek, hogy e részben nincs mitől félned, s hogy az által sohasem
fogunk tönkre jutni. Hála az Istennek, van annyink, hogy abból
könnyen elélhetünk, anélkül, hogy megtagadnók magunktól a
szükségest. Azért kedves Aminém, ne kényszeritsd magad, hanem
egyél ugy, mint engem látsz enni.“
E barátságos móddal, tett észrevételeimre, udvarias feleletet
vártam tőle; azonban egy hangot sem válaszolva, tovább is csak ugy
evett, s hogy még inkább boszantson, csak néha falt egyet a rizsből,
s a helyett, hogy a többi ételből is evett volna velem, csak néha
néha dugott annyi összezsurmolt kenyeret a szájába, a mennyit egy
veréb is felkapott volna.
Agyafurtsága boszanta. Hogy azonban kedvét keressem, s
kimentsem, azt képzelém magamban, hogy nem szokott hozzá
férfiak társaságában enni, annál kevésbbé pedig férjével, kinek
jelenlétében talán tartózkodásra taniták, mit ő együgyüségében
felettébb messze üzött. Azt is gondolám, hogy talán már reggelizett,
vagy ha nem is, akar magának egy kevés étvágyat hagyni, hogy
azután magában tetszése szerint falatozhassék. E gondolataim miatt
semmi olyat sem mondtam neki tovább, a mi elijeszthette, vagy a
miből rosz kedvemnek valami jelét sejdithette volna. Ebéd után
szintoly barátságosan válék el tőle, mintha rendes magaviseletével
legkisebb okot sem adott volna a megelégedetlenségre, s magában
hagyám.
Este szintugy tett, jövő nap is, s átalában véve valahányszor
együtt evénk, mindig szintazon módon viselte magát. Én jól láttam,
hogy egy asszony lehetetlenül élhet oly kevés eledelből el, mint a
mennyit ő veve magához, s következőleg ez alatt más valami
előttem ismeretlen titoknak kell rejtezni. Ez engem tettetésre birt. Én
tehát ugy tevék, mintha nem is figyelnék cselekedeteire, azt
remélve, hogy idővel hozzám szokik, a mint kivántam; reményem
azonban nem sikerült, miről rövid időn meg is kelle győződnöm.
Egy éjjel, midőn Amine engem legmélyebb álomba merültnek
gondola, egész csendességgel felkele, s én észrevevém, hogy a
legnagyobb vigyázattal, nehogy valami zörrenés által felébreszszen,
felöltözködött. Sehogysem foghatám meg, mi czélból háborgatja
nyugalmában magát, s vágyakodva megtudni, mi szándékkal jár,
mély álomban szendergőnek tettetém magam. Egészen felöltözve,
nagy csendességgel mene ki a szobából.
Mihelyt kiment, fölkelék, s magamra öltém köntösömet. Egy az
udvarra szolgáló ablakból észrevehettem, hogy az utczaajtót nyitotta
ki és kiment.
Azonnal az ajtóhoz sieték, melyet félig nyitva hagytam, s utána
suhanék a holdvilágban, mig egy temetőhelybe nem látám bemenni,
mely házunk közelében feküdt. Azonnal egy a temetővel határos
falra mászék, s minekutána jól körülnéztem, nem láthat-e senki,
megpillantám Aminét egy gule-val.1)
Felséged fogja tudni, hogy mindakét nemen lévő gulek a
mezőségen kódorgó rosz lelkek. Rendszerint régi, düledezett
épületekben lappangnak, a honnan az utasokra rohannak, azokat
megölik, s husokat felfalják. Ha nem kapnak utasokat, éjente
temetőhelyekre mennek, hol a kivájott holt testeket emésztik meg.
Én szörnyen megijedtem, midőn nőmet e boszorkánynyal láttam
menni. Egy az nap eltemetett holtat vájtak ki, s a gule több izben
szeldelt le róla hust, melyet a sir karimáján ülve, együtt megettek.
Mig e borzasztó s embertelen eledelt költék el, egész csendességben
beszélgetének együtt, magam azonban sokkal messzebb voltam
tőlök, hogysem beszédökből valamit érthettem volna, mely szintoly
különös lehete, mint vacsorájok, melyre most sem emlékezhetem
vissza borzadás nélkül.
Elvégezvén borzasztó falatozásukat, a holt tetemet ismét a sirba
veték, melyet a kivájott földdel ismét befedének. Én elhagyám őket,
és sietve takarodtam haza. Bejövet az utczaajtót félig nyitva
hagyám, s minekutána hálószobámba érkeztem, lefeküvém ismét, s
alvónak tettetém magamat.
Amine nemsokára egész csendesen bejött az ajtón, levetkezett s
lefeküdt, örömmel teli – mint nekem tetszett – hogy minden oly jól
mene, hogy én észre nem vettem.
Gondolatokba merülve oly embertelen s förtelmes cselekedetről,
milyennek épen most valék szemmel látott tanuja, s teli
idegenséggel a mellett feküdni, ki azt elkövette, igen sokáig tartott,
mig elalhattam. Végre mégis elalvám, de oly gyengéden, hogy az
első szózatra, mely hajnal hasadtával nyilvános imádkozásra szólita,
felserkentem. Felöltözém, s a mecsetbe menék.
Imádság után kimenék a városból, s a reggelt a kertben
sétálással s annak fontolgatásával töltém el, mitevő legyek, nőmet
élete módja változtatására birhatni. Félrevetve minden eszembe
ötlött erőszakos módokat, elhatározám magamban, hogy
szerencsétlen hajlandóságának elszoktatására, csak szelid módokat
használjak. – E fontolgatások közben észrevétlenül jutottam
lakásomig, melybe épen délkor léptem be.
Mihelyt Amine meglátott, tálaltatott s mi ebédhez ülénk.
Minthogy láttam, hogy a rizst még most is folyvást csak szemenkint
eszi, minden, csak lehető szelidséggel mondám neki; „Amine, tudod
mi nagy okom volt összekelésünk utáni első napon csodálkoznom
azon, hogy te csupán a rizsből, ebből is pedig oly furcsa módon
ettél, hogy akármelyik más férj is megbántódott volna általa; tudod
továbbá, hogy én erről elégedetlenségem értésedre adásával
megnyugodtam, s arra kértelek, hogy a többi felhordott, és izlésed
iránti kedvezésből különféle módon készitett husételekből is egyél.
Azóta asztalunk mindig azon módon volt teritve, az étkek közti
némely változást kivéve, nehogy mindig ugyanazt legyünk
kénytelenek enni. Emlékeztetéseim azonban sikeretlenek maradának,
s mind a mai napig sem hagytál fel vele, hanem tovább is rajta vagy,
nekem e boszuságot okozni. Én hallgattam, mivel nem akartalak
kényszeritni, s igen sajnálnám, ha az, a mit jelenben mondok, téged
legkisebbé is megsértene, azonban Amine, mondd meg kérlek, nem
jobb-e az előttünk levő hus a halotti husnál?“
Alig ejtém ki ez utolsó szavaimat, midőn Amine, ki igen jól
sejdité, hogy éjszaka meglestem, minden képzelhetést felülmuló
dühösségre gerjedt, arczulata szinte égett; szemei majd
kidudorodtak fejéből s dühében tajtékzott.
Ezen borzasztó állapotja rémüléssel tölte el; megmeredtem,
tehetetlen voltam ellenem koholt gonoszságától, melyen felséged
maga is fog csodálkozni, megőrizkednem.
Erre legnagyobb hevében egy hozzája közel álló vizmedenczét
ragada meg, ujjai hegyét belemártá, nehány érthetetlen szavat
mormogva, arczul fecskendeze s dühöngő hangon orditá felém:
„Boldogtalan, vedd kiváncsiságod bérét, s
l é g y e b b é .“
Alig mondá ki Amine, kiről eddig még nem tudtam, hogy
boszorkány, ez ördögi szavakat, midőn hirtelen kutyává változottnak
szemlélém magamat. E váratlan változás miatti meglepetésem s
álmélkodásom közben elfelejtkezém eleinte menekedésemre
gondolni, s igy elég ideje volt egy botot ragadni fel, s engem
megkinozni. Valóban oly kegyetlen ütésekkel vendégelt, hogy most
sem foghatom meg, mint maradtam életben. Udvarra szökésemmel
dühét kerülni vélém; azonban ott is szintazon méreggel üldözött, s
bármi fortélyosan bujkáltam is egyik oldalról a másikra ütései
kikerülésére, még sem voltam eléggé tapasztalt az azok elleni
magam védésében, s igy még számos ütést kelle kiállanom. Belé
fáradván végre kinzásomba s üldözésembe, s mintegy kétségbeesve
azon, hogy kivánsága szerint agyonüthessen, ennek végrehajtására
uj módot talála fel. Kinyitá t. i. egy kevéssé az utczaajtót, hogy azon
pillanatban, midőn rajta kisuhanni próbálnék, összeroncsolhasson.
Bármint lettem is pedig kutyává, mégis észrevevém veszélythozó
tervét, s minthogy a rögtöni veszély önszabaditásunkra maga tanit,
magatartására s mozgására vigyázva, jól ellesém az időpontot,
melyben figyelmét megcsalván, hirtelen kisuhantam, s igy mentém
meg életemet s rontám el gonosz szándékát. Egyébként valóban kár
nélkül is menekedtem ki. Azt kivéve, hogy farkam vége egy kevéssé
becsipődött.
Emiatti fájdalmamban orditva s ugatva szaladtam végig az
utczán, s igy vonám magamra több kutya figyelmét, kik meg is
mardostak. Üldözéseik elkerülésére egy ember boltjába ugrám, ki
tisztitott ürüfőket, nyelveket és lábakat árult s hol bátorságban is
voltam.
Az ember először könyörülve véde s szétkergeté az engem üldöző
s szinte házába is betolakodó ebeket. – Részemről az vala első
gondom, hogy egy zugba rejtezkedém, hol nem láthatának. Azonban
itt sem lelém fel a reménylett pártolást és védhelyet. A férfi azon
rendéntuli babonások egyike volt, kik tisztátalan állatnak vélve az
ebet, nem kaphatnak elegendő vizet és szappant ruháik kimosására,
ha csak elmenet ért is hozzájok valami kutya. Minekutána tehát az
engem üldöző ebek eltávoztak, ismételve mindent elkövete, hogy
még aznap üzhessen ki házából; én azonban fürkészései elől biztos
helyre valék elbujva. Igy akarata ellen töltém el az éjt boltjában, s e
nyugalomra valóban szükségem is vala, hogy Amine rosz
bánásmódját valahogy kinyögjem.
Hogy felségedet csekélységek elbeszélésével ne untassam,
elváltozásom felett tett képzelődésimet elhallgatom, s csak azt
jegyzem, hogy következő nap, midőn gazdám, ki korán mene ki
bevásárolni, ürüfőkkel, nyelvekkel s lábakkal terhelve visszatért,
boltját kinyitá s áruit kiraká, én elősompolygék buvóhelyemből, s
minthogy a hus szagára épen látám boltja elébe gyülekezni a
szomszéd ebeket, közéjük elegyedém azon reménynyel, hogy
valamit vet az árus, s kérőleg álltam elébe.
Gazdám figyelni látszék arra, hogy én, nála menekedvén, még
nem ettem semmit is, s avval jelelt ki, hogy többször, és nagyobb
darabokat adogata, mint a többi kutyának. Osztogatása végével
boltjába akarék visszatérni, mely szándékomat ránézéssel és farkam
barátságos csóválgatásával igyekezém tudtára adni, s általa
egyszersmind pártfogása ismétlésére kérni; de ő hajthatatlan vala s
szándékomnak bottal s oly keményszivü tekintettel álla ellen, hogy
kénytelen valék eltávozni.
Nehány házzal odább egy kenyérsütő boltja előtt állék meg, ki
ama komoly ürüfejcsiszárral ellenkezésben vidám s jókedvü
embernek látszott lenni, s valóban az is volt. Épen reggelizett s noha
éhségemnek még épen semmi jelét sem mutattam, mégis egy darab
kenyeret ada. Minekelőtte egyéb kutya módjára telhetetlenül utána
rohannék, főhajtással s farkcsóválással iparkodám neki mintegy
köszönetemet kijelenteni. – Ebbeli udvariasságomat megköszönte s
mosolyga. Én nem valék éhes, hogy azonban kedvében járjak,
felvevém s megevém a kenyeret, még pedig oly lassan, hogy abból
észreveheté, hogy csak az ő kedveért eszem azt. Ezt ő mind
észrevevé s oly szives vala, hogy boltja körül megszenvede. Én tehát
leültem, még pedig arczczal az utcza felé fordulva, annak jeléül,
hogy ezentul csak pártfogásáért esedezem.
Ő ezt nemcsak megengedé, hanem meg is simogata, miből
bizvást észrevehettem, hogy szabad hajlékába bemennem. Én ezt
oly móddal tevém, melyből gyanithatá, hogy azt csak engedelmével
teszem. Nem vevé rosz néven, sőt fekvőhelyet is mutata, hol nem
leendek láb alatt; én azonnal elfoglalám azt, s el sem is hagyám mig
házában valék.
Mindig jól bánt velem, s nem reggelizett, ebédelt, vagy vacsorált,
hogy nekem abból elegendő részt ne juttatott volna. Én részemről
ezért minden kitelhető ragaszkodással és hűséggel viseltettem
iránta, melyet csak kivánhata háladatosságomtól.
Mindig szemmel tartám s egy lépést sem teve házában, hogy ne
követtem volna. Szintazt tevém, ha ideje engedé, hogy dolgaiban a
városba ment. Én e részben annál pontosabb valék, mivel
észrevettem, hogy figyelmem tetszék neki s hogy gyakran, ha
kimenő szándéka volt, s én azt véletlenül észre nem vettem, Piróka
néven, melyet ada, maga után szólita.
E felszólitásra helyemről mindenkor az utczára, ugrottam s ott
futkostam, ugrándoztam s viczkándoztam az ajtó előtt. Ezen
örömjeleket csak kijöttével hagyám félbe s ekkor, előtte vagy utána
futkosva, s örömöm kijelentésére időről időre ránézve, hiven
követém.
Már jó ideig a háznál voltam, midőn egykor egy asszony kenyeret
venni jöve. Midőn gazdámnak azt kifizeté, a többi jó pénz között egy
hamis darabot is ada neki. A sütő, rá ismervén a rosz pénzre,
visszaadá az asszonynak, s mást kivánt helyette.
Az asszony vonakodék azt visszavenni, s jónak állitá. Gazdám az
ellenkezőt vitatá, s szóváltás közben többek között mondja az
asszonynak: „E darab oly szembetünőleg hamis, hogy meg vagyok
győződve, kutyám, mely pedig oktalan állat, sem hagyná magát
azzal rászedni. „Jöszte Piróka!“ mondá tovább engem hiva.
Szólitására azonnal a fizető-asztalon termék. A sütő elém veté a
pénzdarabokat, s mondá: „Nézd meg, nincs-e közte hamis darab?“
Én minden darabot megnéztem, azután a hamisat lábommal
félretoltam, s uramra néztem, mintha mutatni akarnám neki.
A sütő, ki csak véletlenül s tréfából hivatkozék itéletemre, nagyon
meg volt lepetve, midőn látá, hogy én azt oly pontosan s tétovázás
nélkül eltaláltam. Az asszony, ki most pénze hamisságáról meg volt
győződve, elhallgatott, s helyette más jobbat adott. Midőn az
elmene, gazdám összehivá szomszédait, s szerfelett magasztalá
okosságomat, elbeszélvén nekik a történtet.
A szomszédok magok akarának erről meggyőződni, s mindazon
hamis pénzek közül, melyeket jó közé keverve elém adtak, egy sem
volt, hogy azt megismervén ki ne választottam volna.
Az asszony részéről szinte minden előtalált ismerősének
elbeszélte, mi történt vele. A hamis pénzt megismerő ügyességem
hire rövid időn nem csak a szomszédságban, hanem az egész
kerületben, s végre lassanként az egész városban elterjedt.
Ezentúl napestig volt foglalatosságom. Eleget kelle tennem
mindazok kiváncsiságának, kik uramnál vásároltak kenyeret, s meg
kelle mutatnom ügyességemet. Ez az egész várost hozzánk
édesgeté, s legtávolabb kerületekből is eljöttek ügyességem
próbálgatására, s hirem annyi vevőt szerze gazdámnak, hogy alig
elégitheté ki valamennyit. Ez sokáig tartott, s gazdám nem állhatá
meg szomszédaimnak azon vallomást tenni, hogy én neki valóságos
kincs vagyok.
E parányi ügyességem azonban rövid időn irigyeket támaszta
ellene. Utánam leselkedének, hogy elorozhassanak, s ő kénytelen
vala rám szorosan vigyázni. Egy nap jött valamely asszony,
ujságvágyból, szinte mint a többi, s kenyeret vett. Szokott helyem a
fizető-asztalon vala. Előmbe vete hat pénzdarabot, s azok között egy
hamisat is. Kikeresém a többi közül, rá tevém lábomat, s asszonyra
nézék kérdőleg, valjon nem ez-e az?
„Igen,“ felel az asszony, szinte rám nézve, „nem hibáztad el, ez a
hamis.“
Ő engem folyvást csudálkozással szemléle, azalatt hogy én is
szintazt tevém. Erre kifizeté a vásárlott kenyeret, s elmenet inte
utána menni, a nélkül, hogy a sütő észrevette volna.
Én mindig azon voltam, hogy rendes alakváltozásomból
kimenekedhessem. Észrevettem azon figyelmet, melylyel fontolgata
az asszony s én azt képzelém magamban, hogy ő talán sejdite
valamit szerencsétlenségemről s boldogtalan állapotomról; miben
nem is csalatkozám meg. Mindamellett utjának hagyám indulni, s
csak utána néztem. Midőn azonban néhány lépésnyit haladott,
visszafordult, s minthogy látá, hogy mozdulatlanúl nézek utána, ujra
intett hogy kövessem.
Most már nem kétkedém tovább, hanem látván, hogy a sütő
épen kemenczetisztogatással foglalatoskodik uj sütés alá, s rám nem
figyel, leugrottam a fizetőasztalról, s az asszony után szaladék, ki
ezen nagyon látszott örvendeni.
Egy darabig menvén, házához ért, az ajtót kinyitá, bemene, s
mondá hozzám: „Jöszte be; nem fogod megbánni, hogy utánam
jöttél.“ Bemenvén utána, betevé az ajtót, s szobájába vezete, hol
egy rendes szépségü leányt láték himezni. Leánya volt ez a jószivü
asszonynak, ki magával vitt, s a ki, mint mindjárt megtudám, az
igézésben igen ügyes és tapasztalt volt.
„Leányom“ mond az anya „itt hozom neked a sütőnek azon hires
ebét, mely a hamis pénzt oly jól tudja megkülönböztetni a jótól.
Tudod, mit mondtam első hirének terjedésekor, hogy ez valami
gonoszságtól kutyává változtatott ember lehet. Ma eszembe jutott,
hogy a sütőhöz menjek kenyeret venni. Meggyőződtem a hir
valóságáról, s oly szerencsés valék, hogy ezen egész Bagdád-
csodálta kutyát magam után csalhattam. Mit mondasz ehhez
leányom? megcsalódtam talán gyanitásomban?“
„Nem csalódtál meg édes anyám, s én ezt neked mindjárt
megmutatom“ felel a leány.
A leány felkelt, elővett egy vizmedenczét, bemártá ujait,
megfecskendeze, s mondá:
„Ha természettől kutya vagy maradj az; de ha
s z ü l e t é s e d r e n é z v e e m b e r v a g y, e v i z e r e j é n é l
f o g v a v e d d f e l i s m é t e m b e r i a l a k o d a t .“
Azonnal felbomlott az igézés; én elvesztém az ebalakot, s ismét
emberré lettem, mint azelőtt.
E jótét nagyságától általhatva, a leány lábaihoz borulék, s
megcsókolván köntöse szegélyét, mondám neki: „Drágalátos
szabaditóm! példátlan jóságának egy idegen iránt, mint én vagyok,
határtalan mértékét oly annyira érzem, hogy kérem, mondja meg
önmaga, mit tevő legyek, hogy azt illendőképen meghálálhassam,
vagyis inkább, parancsoljon velem, mint teljes joggal saját
rabszolgájával. Én többé nem vagyok magamé, hanem a magáé; s
hogy azt, kit sajátjává teve, közelebbről megismerhesse, röviden
elbeszélem történetemet.“
Erre megmondám ki legyek, s azután elbeszélém összekelésemet
Aminével, azon udvariságot s türedelmet, melylyel elviselém
szeszélyeit, továbbá rendes magaviseletét, s azon méltatlan
bánásmódot, melylyel megfejthetetlen gonoszságában kinoza, s
szavaimat az épen most szerzett kimondhatatlan szerencséért, az
anyjához intézett köszönetemmel fejezém be.
„Sidi Numan,“ szól hozzám a leány „hallgass el ezentul
köszönetedről, melylyel nekem tartozni véled magadat. Annak puszta
tudása, hogy örömet szereztem oly derék férfiunak, mint te vagy,
kipótol nálam minden köszönetet. Beszéljünk inkább Amine
hitvesedről. Még hajadon korában ismerém, s valamint én tudám
róla, hogy igéző, szintugy én sem valék előtte ismeretlen, mint e
mesterséghez szintén egy keveset értő, minthogy ugyanazon egy
mesterasszonytól vevők oktatásunkat. Gyakran találkozánk a
fürdőben. De minthogy természetünk nem illett össze, szorgosan
kerülék minden alkalmat, vele valamely összeköttetésbe jőni, a mi
reám nézve annyival könnyebb volt, mivel ő is viszont szint e
tekintetből került velem minden közlekedést. Én tehát épen nem
csudálkozom gonoszságán. Hogy azonban ismét reád kerüljünk, még
az sehogysem elég, a mit éretted épen most tevék; a mibe fogtam,
végre is szándékozom hajtani. Még az valóban nem elég, hogy
felmentélek azon igézés alul, mely gonoszul zára ki minden emberi
társaságból, te is büntesd meg őt érdeme szerint, mi végre térj
házadba, s szerezd vissza a neked járó tekintetet, mihez a szükséges
eszközöket és módot kezedbe szolgáltatom. Mulasd magad egy
kevéssé anyámmal, én azonnal visszatérek.“
Szabaditóm most egy kis mellékterembe mene, s mig abban
mulata, uj alkalmam adaték az anyjának kinyilatkoztathatnom, mi
nagy hálával tartozom leánya s ő iránta.
„Leányom“ mondá hozzám „mint látod, szintugy ért az igézéshez,
mint Amine, de ő ezt oly jól használja, hogy csudálkoznál, ha
tudnád, mi sok jót tett már, s tesz naponkint e tudományával. Ezért
mindeddig hagyám munkálódni, s hagyom most is. Ha észrevenném,
hogy legkisebbé is visszaélne tudományával, nem szenvedném.“
Az anyja épen néhány ilyen csodálatos történet elbeszéléséhez
foga, melyeket maga látott, midőn leánya egy kis üveggel belépe.
„Sidi Numan, – monda ő hozzám – könyveim, melyeket épen
megtekinték, nekem azt mondják, hogy Amine e szempillanatban
nincs otthon, de hogy mindjárt hazatérend. Mondják továbbá, hogy
a hűtelen szolgáid előtt ugy tetteti magát, mintha távolléted miatt
nagy nyugtalanságban volna, s elhitette velök, hogy neked ebéd
alatt valami dolog juta eszedbe, mely miatt haladék nélkül valál
kénytelen kimenni, elmenet nyitva hagyád az ajtót, mire egy kutya
jöve be, s az ebédlőbe szalada, melyet is bottal kelle elüznie. Térj
azért haladék nélkül e kis üveggel vissza házadba. Ha bebocsátottak,
Amine visszatértét szobádban várd be, mert nem sokáig fog már
kimaradni. E váratlan viszontlátás miatti zavarában hátat forditva,
szökésnek ered; ekkor az üvegben levő s készentartott vizből locsolj
reá, s egész bátorsággal e szavakat mondd:
„ F o g a d d e z e n n e l g o n o s z s á g o d b ü n t e t é s é t .“
„Többet nem mondok; sikerét majd meglátod.“
Jótevőm felejthetetlen szavai után, minthogy már semmi sem
gátola, tőle s anyjától elbucsúzám, s a legtökéletesebb hála
érzeteivel, hogy örökké fogok emlékezni az irántuk tartozó
köteleztetésimről, hazatértem.
Minden ugy történt, mint jövendölé a fiatal igéző. Amine nem
mulata sokáig. Közeledvén, elébe menék a vizzel, hogy
meglocsoljam. Hangosan sikolta, s midőn hátat forditva az ajtó felé
sietett, meglocsolám a vizzel s az igézőtől tanult szavakat mondám
hozzá. Rögtön kanczává, még pedig azzá változott, melyet felséged
tegnap láta.
Meglepetése közepette azonnal üstökön kaptam, minden
hánykolódása ellen is ólamba vezetém, kötőféket veték fejére s
minekutána gonoszsága s csinje miatti legkeményebb
szemrehányások között bekötém, kifáradásig ostorozám; s feltevén
magamban, hogy mindennap igy bánok vele.
Igazhitüek uralkodója, – folytatá Sidi Numan elbeszélését
végezve, – bátorkodom reményleni, hogy felséged helybenhagyja
magamviseletét, s elismeri, hogy ily gonosz és veszedelmes
asszonynyal érdemén felüli lágysággal bántam.
Hallván a chalyf Sidi Numan beszédének végét, mondja hozzá:
„Történeted jeles a maga nemében, s feleséged gonoszsága
megbocsáthatatlan. Nem is kárhoztatom egészen eddigi bünhödését.
Szeretném azonban, ha meggondolnád, mi nagy büntetés neki már
állattá alacsonyodása is, s megelégednél avval, hogy büneiért ez
állapotban hagynád lakolni, sőt parancsolnám is, hogy folyamodjál
azon fiatal igézőhöz, ki e változást eszközlé, s birnád rá az igézés
másitására, ha ismeretes nem volna előttem az olyan igézők
nyakassága s örökre javithatlan gonoszsága, kik tudományukkal
visszaélnek, s ha részéről nem tartanék az ellened való
boszuállásától, mely sokkal gonoszabbul üthetne ki az elsőnél.“
A chalyf, ki szenvedők iránt, még ha megérdemlették is,
természettől szelid és szánakodó vala, kijelentvén Sidi Numannak
vélekedését, a harmadik felé fordult a három közül, kiket Giafar
nagyvezér rendele meg.
„Kodjah Hasszán“ mond ehhez, „midőn tegnap házad előtt
elmenék, az nekem oly pompásnak tetszék, hogy tudni kivántam,
kié? Értésemre esett, hogy te épittetéd, ki azelőtt oly mesterséget
üztél, melynek jövedelméből alig juta elegendő mindennapi
kenyérre. Hallám egyuttal, hogy nem bizod el magad, hogy az
Istentől nyert gazdagságnak jó hasznát veszed, s hogy szomszédid
ezer jót beszélnek rólad. Mindezen, mond a chalyf, nagyon örvendek,
s meg vagyok győződve, hogy azon utnak és módnak, mely által
tetszett a végzésnek téged részesitni javaiban, egészen rendkivülinek
kell lennie. Szeretném ezt tőled magadtól megtudni, mely
kivánságom teljesitésére hivattalak. Szólj velem azért egész
nyiltszivüleg, hogy annál nagyobb örömmel s belátással
részesülhessek szerencsédben. – Hogy azonban kiváncsiságom
előtted gyanussá ne tegyen, s te talán azt ne véljed, hogy más
valami önhaszonkereső részt akarok venni szerencsédben, ezennel
kijelentem, hogy nemcsak magamévá nem akarom tenni semmi
ürügy alatt is, hanem inkább pártfogásomat ajánlom, hogy
háboritatlan békében vehessed hasznát.“
A chalyfnak e szavaira Kodjah Hasszán a fejedelmi szék elé
borulva, homlokával érinté a ráboritott szőnyeget, s felkelvén,
mondá: „Igazhitüek uralkodója! Akárki is, kinek lelkiismerete nem oly
tiszta és szeplőtelen, mint az enyém, megijedett volna a felséged
szine elébe idéző parancsolat vételekor. De minthogy én felséged
iránt még gondolatimban is mindig tisztelettel s alázatossággal
viseltetem, és soha sem a felséged iránti köteles engedelmesség,
sem a törvények ellen nem vétettem semmi olyat, a mi haragját
legkisebbé is gerjeszthette volna ellenem, csak az az egy ejte
aggodalomba, hogy felséged fényét nem fogom eltürhetni. Mivel
azonban a közhir szerint felséged legcsekélyebb alattvalóját is oly
különös jósággal fogadja és hallgatja, ismét megnyugvám, s nem is
kételkedém, hogy önmaga fog a kivánt értesitésre bátoritni. Ezt
felséged csak épen most tevé, midőn hathatós pártfogásáról
bizonyossá tőn, anélkül, hogy tudná, megérdemlem-e vagy sem. De
reménylem is, hogy nem másolandja meg irántam való kegyes
vélekedéseit, ha parancsolatát teljesitve, történeteimet elbeszéltem.“
E tisztes megszólitás után, melylyel a chalyf kegyességét s
figyelmét kivánta megnyerni, s minekutána a mondandókról egy
kevéssé gondolkodék, következő szavakkal kezdé Kodjah Hasszan
történetét:

Kodjah Hasszan Alhabbal története.


Igazhitüek uralkodója – imigy kezdé – hogy felségednek jobban
megmutathassam, miként jutottam jelenleg általam birt
vagyonomhoz, legelébb is két igen meghitt barátról kell
emlékeznem, kik e Bagdad városa még életben lévő polgárai, s
beszédem igaz voltáról bizonyságot tehetnek. Isten, mint minden
jónak kezdője után, egyenest nekik köszönhetem szerencsémet.
E két jó barátok egyikének Saadi, másiknak Saad a neve. Saadi,
ki felettébb gazdag, mindig azt vitatta, hogy e világon csak ugy lehet
az ember boldog, ha annyi kincscsel bir, hogy minden embertől
függetlenül élhessen.
Saad más vélekedésen van. Ő ugyan megengedi azt, hogy kell
birni gazdagsággal, a mennyiben az t. i. az élet fentartására
szükséges; ő azonban azt állitja, hogy az erénynek kell az emberek
boldogságát tennie, a nélkül hogy ezek tovább aggódnának e világi
javakról, mint a mennyiben azok szükségeik kielégitésére, s mások
iránti jóságos cselekedetek adakoztatására szükséges. Saad ezen
emberekhez tartozik, s ő jelen körülményi között igen szerencsésen s
megelégedetten él. Noha Saadi hozzá képest úgyszólván véghetlenül
gazdag, mindamellett barátságok igen szoros és igazlelkü, s a
gazdagabbik magát sem tartja többnek amannál. Ez egyetlen pontot
kivéve, mindig egyet értettek még mindenben.
Egykor Saadi beszédközben e tárgyról, – mint nekem azután
mindaketten beszélték, – azt állitá, hogy a szegények csak azért
szegények, mivel vagy szegénységben születtek, vagy pedig, ha
vagyonosak voltak is születésökre nézve, vagyonjokat vagy
eltékozlották, vagy, a mi nem ritka, valamely előre nem látott eset
által elvesztették. „Vélekedésem szerint“ mond ő folytatólag „ezen
szegények csak azért szegények, mivel nem birnak összeszerezni oly
összeg pénzt, mely elegendő volna, hogy szorgalmas forgatása által
nyomoruságukból kiragadná, s én azt tartom, ha valaha e pontra
juthatnának, s e summának illendő hasznát vennék, idővel nem csak
gazdagokká, hanem igen tehetősekké is lennének.
Saad Saadi állitását nem akarta helybenhagyni. „A tőled ajánlott
mód,“ mond ez „egy szegénynek gazdagithatására, előttem nem
látszik oly biztosnak, mint gondolod. Ebbeli vélekedésed nem eléggé
alapos, s én ennek ellenében a magamét több jó okkal
támogathatnám, de a melyek messze vinnének. Én azt hiszem, s
legalább szintannyi hihetőséggel, hogy egy szegény hamarább
meggazdagszik akármi által is, mint állitásod szerint egy összeg pénz
által, – bármi takarékosan s gazdaságosan forgassa is, hogy jól vitt
dolgai által szaporithassa.“
„Saad,“ mond Saadi, „jól látom, hogy veled semmire sem
mennék, ha tovább is védelmezném vélekedésemet a tied ellen;
hanem inkább magam teszek próbát, hogy meggyőzzelek felőle, s p.
o. egy összeg pénzt, mely elegendőnek fog látszani, azon
mesteremberek egyikének fogom ajándékozni, ki szegény
származású lévén, mindennapi keresményéből él, s azon
nyomorúságban hal meg, melyben születék. Ha nekem ez nem sül
el, megkisértjük, a vélekedésed szerinti úton jobban megyen-e?“
Néhány napra e szóváltás után a két barát a város azon részébe
jutott sétálás közben, hol én kötélgyártó mesterségemet üztem,
melyet atyámtól tanultam, ez pedig nagy apámtól, családunk
törzsökétől tanulta. Ki öltözetemet s köntösömet látá, könnyen
kitanulhatá belőlök szegénységemet.
Saad, emlékezvén Saadi szavaira, monda ehhez: „Ha tán el nem
felejtéd, mire kötelezéd magad irántam, ime van egy ember, reám
mutatva – kit már régen látok állandó szegénységében köteleit
gyártani. Ez bőkezüségedre egészen méltó tárgy, s a minap
emelitetted próbatételre egészen alkalmas.“
„Jól emlékezem róla“ mond Saadi, „hogy az óta folyvást annyi
pénzt hordok magammal, a mennyi ily nemü próbatételre szükséges,
és csak olyan alkalomra vártam, hol magad szemmel látott tanú
lehetsz. Szólitsuk meg, s tudjuk ki, van-e valóban pénzre szüksége.“
A két jó barát felém tarta, s látván, hogy velem szólani akarnak,
félbenhagyám munkámat. Szokás szerint minden jót kivánva
szólitának meg, s Saadi nevem tudakolásán kezdé a beszédet.
Én viszonozván a köszöntést, Saadi kérdésére felelve mondám:
„Uram, az én nevem Hasszan, s mesterségem miatt Hasszan
Alhabbal név alatt vagyok ismeretes közönségesen.“
„Hasszán“ mond erre Saadi, „minthogy nincs oly mesterség, mely
el ne birná tartani mesterét, nem kételkedem, hogy a kelmedé is hoz
be annyit, a mennyi illendő elélhetésére elegendő, s magam is
csudálkozom, hogy mióta kelmed ezt üzi, nem takaritott magának
annyit, hogy nagyobb mennyiségü kendert vásárolván, több munkát
végezhetne mind maga, mind fogadott legények által, élete
könnyebbitésére.“
„Uram“ felelém neki, „nem fogna csodálkozni, hogy nem
takaritottam semmit is, és nem indulok gazdagodni a javaslott uton,
ha tudná, hogy egész napi összes munkámmal alig vagyok képes
annyit keresni, a mennyi szükséges magam s családom kenyérrel s
főzelékkel táplálatára. Van feleségem s öt gyermekem, kik közül még
egy sincs akkora, hogy csak legkevésbbé is segithetne; kell számokra
élelem és ruházat, s egy gazdaság körül, bármi kicsi legyen is,
mindig akad ezerféle szükség, melyet nem igen mellőzhetni. Noha a
kender nem drága, mégis pénz kell beszerzésére, s ez mindig az
első, a mit munkám szerzeményéből félre kell tennem, különben
nem volnék képes annyit keresni, a mennyi házi szükségeimre kell.
Könnyen elgondolhatja most édes ur“ folytatám tovább, „lehetséges-
e annyit szereznem, hogy magamat s családomat jobb lábra
állithassam. Nekünk elég, ha azon kevéssel, mit isten ád,
megelégszünk, s hogy nem gerjeszté fel még bennünk annak
kivánását, a mi talán hibázik tőlünk; sőt inkább ugy tapasztaljuk,
hogy semmink sem hibázik, mihelyt ki van elégitve mindennapi
szükségünk, s mi nem vagyunk miatta kénytelenek senkinek is
terhére esni.“
Midőn mind ezeket oly körülményesen mondám Saadinak, felelé
nekem: „Hasszan, már nem csodálkozom többé, igen jól értem, mért
kelle megelégedned jelen állapotoddal. De ha ajándékoznék egy
erszényt kétszáz aranynyal, jól vennéd-e hasznát, s mit gondolsz,
ezen összeggel nem lennél-e rövid idő mulva legalább is olyan
gazdaggá, mint a mesterségedbeli legjelesebbek?“
„Uram“ viszonzám, oly derék embernek tartom, hogy meg vagyok
győződve, nem üzi velem talán csak tréfáját, hanem ajánlása való.
Azért bátorkodom kinyilatkoztatni, hogy sokkal csekélyebb summa is
elegendő volna, nem csak oly gazdaggá lennem, mint a sorsombeli
legelsők, hanem rövid idő mulva gazdagabbá is, mint e kiterjedt és
népes Bagdad nagy városának valamennyie összevéve.“
A nagylelkü Saadi csakhamar be is bizonyitá, hogy igazat beszélt,
kihuzá erszényét kebléből, s kezembe adá e szavakkal: „Nesze ez az
erszény, a kétszáz aranyat hiány nélkül megleled benne. Én kérem az
istent, áldását adja hozzá, s részesitsen malasztjában, hogy jól
vehessed hasznát. Bizonyos lehetsz egyuttal a felől is, hogy én és
Saad barátom itten, igen fogunk örülni, ha halljuk, hogy általunk
szerencsésebbé lettél, mint most vagy.“
Midőn én, igazhitüek uralkodója, az erszényt kaptam, s keblembe
rejtettem, egészen át valék hatva gyönyörtől és hálaérzettől, hogy a
szavam is elállott, s hogy nekem lehetetlen vala ezt jótevőmnek
másként kijelenthetni, hanem hogy ruhája szegélyéért nyultam,
megcsókolás végett; de ő kitére, s utjának indula barátjával.
Eltávozásuk után munkámhoz fogván, első dolgom az volt, az
erszény eltevésére biztos helyről gondoskodni. Nyomoru kis
hajlékomban t. i. sem szekrényem, sem ládám nem volt, melyet
elzárhattam volna, sem más oly biztos helyem, hova hamar
felfedeztetés félelme nélkül elrejthettem volna.
Minthogy én is hozzám hasonló emberek szokása szerint kevés
pénzecskémet csalmám (turbán) ránczaiban hordoztam, e
kétkedésem közben félbehagyám munkámat, s hazatértem, csalmám
rendbeszedésének ürügye alatt. A dolgot oly vigyázva tevém meg,
hogy feleségem s gyermekim tudta nélkül tiz aranyat kivéve az
erszényből legnagyobb szükségeim fedezésére, a többit azon vászon
ránczai közé göngyölém, melylyel sapkámat szoktam körülövedzeni.
Még aznap tett első kiadásom abból álla, hogy jó sok kendert
vásároltam, s ezután, – minthogy már régen nem volt husétel
asztalomon, – mészárszékbe menék hust venni.

You might also like