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

The Python 3 Standard Library By Example Hellmann Doug instant download

The document provides information about 'The Python 3 Standard Library By Example' by Doug Hellmann, including links to download various editions and related Python programming books. It also features a brief overview of the Musée d’Orsay in Paris, detailing its history and significance as a museum. Additionally, the document outlines the Developer's Library series, which offers high-quality programming references and tutorials.

Uploaded by

drzalgerth8u
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

The Python 3 Standard Library By Example Hellmann Doug instant download

The document provides information about 'The Python 3 Standard Library By Example' by Doug Hellmann, including links to download various editions and related Python programming books. It also features a brief overview of the Musée d’Orsay in Paris, detailing its history and significance as a museum. Additionally, the document outlines the Developer's Library series, which offers high-quality programming references and tutorials.

Uploaded by

drzalgerth8u
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 85

The Python 3 Standard Library By Example

Hellmann Doug download

https://ebookbell.com/product/the-python-3-standard-library-by-
example-hellmann-doug-21354604

Explore and download more ebooks at ebookbell.com


Here are some recommended products that we believe you will be
interested in. You can click the link to download.

The Python 3 Standard Library By Example Second Doug Hellmann

https://ebookbell.com/product/the-python-3-standard-library-by-
example-second-doug-hellmann-5913574

The Python 3 Standard Library By Example 1st Edition Doug Hellmann

https://ebookbell.com/product/the-python-3-standard-library-by-
example-1st-edition-doug-hellmann-6735550

Cpython Internals Your Guide To The Python 3 Interpreter 1st Edition


Anthony Shaw

https://ebookbell.com/product/cpython-internals-your-guide-to-the-
python-3-interpreter-1st-edition-anthony-shaw-11947410

Cpython Internals Your Guide To The Python 3 Interpreter 1st Edition


Anthony Shaw

https://ebookbell.com/product/cpython-internals-your-guide-to-the-
python-3-interpreter-1st-edition-anthony-shaw-49565250
Network Programming In Python The Basic A Detailed Guide To Python 3
Network Programming And Management John Galbraith

https://ebookbell.com/product/network-programming-in-python-the-basic-
a-detailed-guide-to-python-3-network-programming-and-management-john-
galbraith-43743954

Learn Python 3 The Hard Way A Very Simple Introduction To The


Terrifyingly Beautiful World Of Computers And Code Pdfdrivecom Zed A
Shaw

https://ebookbell.com/product/learn-python-3-the-hard-way-a-very-
simple-introduction-to-the-terrifyingly-beautiful-world-of-computers-
and-code-pdfdrivecom-zed-a-shaw-50384078

Learn Python 3 The Hard Way A Very Simple Introduction To The


Terrifyingly Beautiful World Of Computers And Code Zed A Shaw

https://ebookbell.com/product/learn-python-3-the-hard-way-a-very-
simple-introduction-to-the-terrifyingly-beautiful-world-of-computers-
and-code-zed-a-shaw-43272374

Learn Python 3 The Hard Way A Very Simple Introduction To The


Terrifyingly Beautiful World Of Computers And Code Alan Mainwarings
Library Zed A Shaw

https://ebookbell.com/product/learn-python-3-the-hard-way-a-very-
simple-introduction-to-the-terrifyingly-beautiful-world-of-computers-
and-code-alan-mainwarings-library-zed-a-shaw-230941080

Learn Python 3 The Hard Way A Very Simple Introduction To The


Terrifyingly Beautiful World Of Computers And Code Zed Shaws Hard Way
Series Zed A Shaw

https://ebookbell.com/product/learn-python-3-the-hard-way-a-very-
simple-introduction-to-the-terrifyingly-beautiful-world-of-computers-
and-code-zed-shaws-hard-way-series-zed-a-shaw-31700994
Musée d’Orsay, Paris, France
Located on the Seine’s left bank, the Musée d’Orsay
is housed in a breathtaking Beaux-Arts building originally
designed as the world’s first electrified urban railway
station. The original “Gare d’Orsay” was built on the
site of the old Palais d’Orsay, which had lain empty
since it burned in 1871 during the Paris Commune.
The building opened on Bastille Day, July 14, 1900,
to help celebrate Paris’s Fifth Universal Exhibition.
Designated a Historical Monument in 1978, it was
then recreated as a museum by Renaud Bardon,
Pierre Colboc, and Jean-Paul Philippon of the ACT
architecture group. Per the museum’s official history,
the new architects “highlighted the great hall, using
it as the main artery of the visit, and transformed
the magnificent glass awning into the museum’s
entrance.” Inside, Gae Aulenti adapted the enormous
station into museum spaces, unified via consistent
stone wall and floor surfaces. Opened in 1986,
the new museum brought together three major
art collections from the era 1848-1914. More than
three million visitors now come every year to see
works from artists including Cézanne, Courbet,
Degas, Gauguin, Manet, Monet, and Renoir.
The Python 3
Standard Library
by Example
Developer’s Library

Visit informit.com/devlibrary for a complete list of available publications.

The Developer’s Library series from Addison-Wesley provides practicing


programmers with unique, high-quality references and tutorials on the latest
programming languages and technologies they use in their daily work. All
books in the Developer’s Library are written by expert technology practioners
who are exceptionally skilled at organizing and presenting information in a
way that is useful for other programmers.

Developer’s Library titles cover a wide range of topics, from open source
programming languages and technologies, mobile application development,
and web development to Java programming and more.
The Py thon 3
Standard Library
by Example

Doug Hellmann

Boston • Columbus • Indianapolis • New York • San Francisco • Amsterdam • Cape Town
Dubai • London • Madrid • Milan • Munich • Paris • Montreal • Toronto • Delhi • Mexico City
São Paulo • Sydney • Hong Kong • Seoul • Singapore • Taipei • Tokyo
Many of the designations used by manufacturers and sellers to distinguish their products are claimed as
trademarks. Where those designations appear in this book, and the publisher was aware of a trademark
claim, the designations have been printed with initial capital letters or in all capitals.

The author and publisher have taken care in the preparation of this book, but make no expressed or
implied warranty of any kind and assume no responsibility for errors or omissions. No liability is assumed
for incidental or consequential damages in connection with or arising out of the use of the information or
programs contained herein.

For information about buying this title in bulk quantities, or for special sales opportunities (which
may include electronic versions; custom cover designs; and content particular to your business, train-
ing goals, marketing focus, or branding interests), please contact our corporate sales department at
corpsales@pearsoned.com or (800) 382-3419.

For government sales inquiries, please contact governmentsales@pearsoned.com.

For questions about sales outside the U.S., please contact intlcs@pearson.com.

Visit us on the Web: informit.com/aw

Library of Congress Control Number: 2017932317

Copyright © 2017 Pearson Education, Inc.

All rights reserved. Printed in the United States of America. This publication is protected by copyright, and
permission must be obtained from the publisher prior to any prohibited reproduction, storage in a retrieval
system, or transmission in any form or by any means, electronic, mechanical, photocopying, recording, or like-
wise. For information regarding permissions, request forms and the appropriate contacts within the Pearson
Education Global Rights & Permissions Department, please visit www.pearsoned.com/permissions/.

ISBN-13: 978-0-13-429105-5
ISBN-10: 0-13-429105-0

1 17
For Theresa,
my one true love.
This page intentionally left blank
Contents at a Glance
Introduction xxxi

Acknowledgments xxxiii

About the Author xxxv

Chapter 1 Text 1

Chapter 2 Data Structures 65

Chapter 3 Algorithms 143

Chapter 4 Dates and Times 211

Chapter 5 Mathematics 239

Chapter 6 The File System 295

Chapter 7 Data Persistence and Exchange 395

Chapter 8 Data Compression and Archiving 477

Chapter 9 Cryptography 523

Chapter 10 Concurrency with Processes, Threads, and Coroutines 535

Chapter 11 Networking 687

Chapter 12 The Internet 753

Chapter 13 Email 841

Chapter 14 Application Building Blocks 887

Chapter 15 Internationalization and Localization 1003

Chapter 16 Developer Tools 1023

Chapter 17 Runtime Features 1169

Chapter 18 Language Tools 1279


vii
viii Contents at a Glance

Chapter 19 Modules and Packages 1329

Appendix A Porting Notes 1351

Appendix B Outside of the Standard Library 1367

Index of Python Modules 1373

Index 1375
Contents
Introduction xxxi

Acknowledgments xxxiii

About the Author xxxv

Chapter 1 Text 1
1.1 string: Text Constants and Templates 1
1.1.1 Functions 1
1.1.2 Templates 2
1.1.3 Advanced Templates 4
1.1.4 Formatter 6
1.1.5 Constants 6
1.2 textwrap: Formatting Text Paragraphs 7
1.2.1 Example Data 8
1.2.2 Filling Paragraphs 8
1.2.3 Removing Existing Indentation 8
1.2.4 Combining Dedent and Fill 9
1.2.5 Indenting Blocks 10
1.2.6 Hanging Indents 12
1.2.7 Truncating Long Text 12
1.3 re: Regular Expressions 13
1.3.1 Finding Patterns in Text 14
1.3.2 Compiling Expressions 15
1.3.3 Multiple Matches 16
1.3.4 Pattern Syntax 17
1.3.5 Constraining the Search 28
1.3.6 Dissecting Matches with Groups 30
1.3.7 Search Options 36
1.3.8 Looking Ahead or Behind 44
1.3.9 Self-referencing Expressions 48
1.3.10 Modifying Strings with Patterns 53
1.3.11 Splitting with Patterns 55
1.4 difflib: Compare Sequences 58
1.4.1 Comparing Bodies of Text 58
1.4.2 Junk Data 61
1.4.3 Comparing Arbitrary Types 62

ix
x Contents

Chapter 2 Data Structures 65


2.1 enum: Enumeration Type 66
2.1.1 Creating Enumerations 66
2.1.2 Iteration 67
2.1.3 Comparing Enums 67
2.1.4 Unique Enumeration Values 69
2.1.5 Creating Enumerations Programmatically 71
2.1.6 Non-integer Member Values 72
2.2 collections: Container Data Types 75
2.2.1 ChainMap: Search Multiple Dictionaries 75
2.2.2 Counter: Count Hashable Objects 79
2.2.3 defaultdict: Missing Keys Return a Default Value 83
2.2.4 deque: Double-Ended Queue 84
2.2.5 namedtuple: Tuple Subclass with Named Fields 89
2.2.6 OrderedDict: Remember the Order Keys Are Added to a Dictionary 94
2.2.7 collections.abc: Abstract Base Classes for Containers 97
2.3 array: Sequence of Fixed-Type Data 98
2.3.1 Initialization 98
2.3.2 Manipulating Arrays 99
2.3.3 Arrays and Files 100
2.3.4 Alternative Byte Ordering 101
2.4 heapq: Heap Sort Algorithm 103
2.4.1 Example Data 103
2.4.2 Creating a Heap 104
2.4.3 Accessing the Contents of a Heap 105
2.4.4 Data Extremes from a Heap 107
2.4.5 Efficiently Merging Sorted Sequences 108
2.5 bisect: Maintain Lists in Sorted Order 109
2.5.1 Inserting in Sorted Order 109
2.5.2 Handling Duplicates 110
2.6 queue: Thread-Safe FIFO Implementation 111
2.6.1 Basic FIFO Queue 112
2.6.2 LIFO Queue 112
2.6.3 Priority Queue 113
2.6.4 Building a Threaded Podcast Client 114
2.7 struct: Binary Data Structures 117
2.7.1 Functions Versus Struct Class 117
2.7.2 Packing and Unpacking 117
2.7.3 Endianness 118
2.7.4 Buffers 120
2.8 weakref: Impermanent References to Objects 121
2.8.1 References 122
2.8.2 Reference Callbacks 122
2.8.3 Finalizing Objects 123
2.8.4 Proxies 126
2.8.5 Caching Objects 127
Contents xi

2.9 copy: Duplicate Objects 130


2.9.1 Shallow Copies 130
2.9.2 Deep Copies 131
2.9.3 Customizing Copy Behavior 132
2.9.4 Recursion in Deep Copy 133
2.10 pprint: Pretty-Print Data Structures 136
2.10.1 Printing 136
2.10.2 Formatting 137
2.10.3 Arbitrary Classes 138
2.10.4 Recursion 139
2.10.5 Limiting Nested Output 139
2.10.6 Controlling Output Width 140

Chapter 3 Algorithms 143


3.1 functools: Tools for Manipulating Functions 143
3.1.1 Decorators 143
3.1.2 Comparison 151
3.1.3 Caching 155
3.1.4 Reducing a Data Set 158
3.1.5 Generic Functions 161
3.2 itertools: Iterator Functions 163
3.2.1 Merging and Splitting Iterators 164
3.2.2 Converting Inputs 167
3.2.3 Producing New Values 169
3.2.4 Filtering 172
3.2.5 Grouping Data 175
3.2.6 Combining Inputs 176
3.3 operator: Functional Interface to Built-in Operators 183
3.3.1 Logical Operations 183
3.3.2 Comparison Operators 184
3.3.3 Arithmetic Operators 184
3.3.4 Sequence Operators 186
3.3.5 In-Place Operators 187
3.3.6 Attribute and Item “Getters” 188
3.3.7 Combining Operators and Custom Classes 190
3.4 contextlib: Context Manager Utilities 191
3.4.1 Context Manager API 191
3.4.2 Context Managers as Function Decorators 194
3.4.3 From Generator to Context Manager 196
3.4.4 Closing Open Handles 198
3.4.5 Ignoring Exceptions 199
3.4.6 Redirecting Output Streams 201
3.4.7 Dynamic Context Manager Stacks 202
xii Contents

Chapter 4 Dates and Times 211


4.1 time: Clock Time 211
4.1.1 Comparing Clocks 211
4.1.2 Wall Clock Time 213
4.1.3 Monotonic Clocks 214
4.1.4 Processor Clock Time 214
4.1.5 Performance Counter 216
4.1.6 Time Components 217
4.1.7 Working with Time Zones 218
4.1.8 Parsing and Formatting Times 219
4.2 datetime: Date and Time Value Manipulation 221
4.2.1 Times 221
4.2.2 Dates 222
4.2.3 timedeltas 225
4.2.4 Date Arithmetic 226
4.2.5 Comparing Values 228
4.2.6 Combining Dates and Times 228
4.2.7 Formatting and Parsing 230
4.2.8 Time Zones 231
4.3 calendar: Work with Dates 233
4.3.1 Formatting Examples 233
4.3.2 Locales 236
4.3.3 Calculating Dates 236

Chapter 5 Mathematics 239


5.1 decimal: Fixed- and Floating-Point Math 239
5.1.1 Decimal 239
5.1.2 Formatting 241
5.1.3 Arithmetic 242
5.1.4 Special Values 243
5.1.5 Context 244
5.2 fractions: Rational Numbers 250
5.2.1 Creating Fraction Instances 250
5.2.2 Arithmetic 252
5.2.3 Approximating Values 253
5.3 random: Pseudorandom Number Generators 254
5.3.1 Generating Random Numbers 254
5.3.2 Seeding 255
5.3.3 Saving State 255
5.3.4 Random Integers 257
5.3.5 Picking Random Items 258
5.3.6 Permutations 258
5.3.7 Sampling 260
5.3.8 Multiple Simultaneous Generators 261
5.3.9 SystemRandom 262
5.3.10 Non-uniform Distributions 263
Contents xiii

5.4 math: Mathematical Functions 264


5.4.1 Special Constants 265
5.4.2 Testing for Exceptional Values 265
5.4.3 Comparing 267
5.4.4 Converting Floating-Point Values to Integers 270
5.4.5 Alternative Representations of Floating-Point Values 271
5.4.6 Positive and Negative Signs 272
5.4.7 Commonly Used Calculations 274
5.4.8 Exponents and Logarithms 278
5.4.9 Angles 282
5.4.10 Trigonometry 284
5.4.11 Hyperbolic Functions 288
5.4.12 Special Functions 289
5.5 statistics: Statistical Calculations 290
5.5.1 Averages 290
5.5.2 Variance 292

Chapter 6 The File System 295


6.1 os.path: Platform-Independent Manipulation of Filenames 296
6.1.1 Parsing Paths 296
6.1.2 Building Paths 300
6.1.3 Normalizing Paths 301
6.1.4 File Times 302
6.1.5 Testing Files 303
6.2 pathlib: File System Paths as Objects 305
6.2.1 Path Representations 305
6.2.2 Building Paths 305
6.2.3 Parsing Paths 307
6.2.4 Creating Concrete Paths 309
6.2.5 Directory Contents 309
6.2.6 Reading and Writing Files 312
6.2.7 Manipulating Directories and Symbolic Links 312
6.2.8 File Types 313
6.2.9 File Properties 315
6.2.10 Permissions 317
6.2.11 Deleting 318
6.3 glob: Filename Pattern Matching 319
6.3.1 Example Data 320
6.3.2 Wildcards 320
6.3.3 Single-Character Wildcard 321
6.3.4 Character Ranges 322
6.3.5 Escaping Meta-characters 322
6.4 fnmatch: Unix-Style Glob Pattern Matching 323
6.4.1 Simple Matching 323
6.4.2 Filtering 325
6.4.3 Translating Patterns 325
xiv Contents

6.5 linecache: Read Text Files Efficiently 326


6.5.1 Test Data 326
6.5.2 Reading Specific Lines 327
6.5.3 Handling Blank Lines 328
6.5.4 Error Handling 328
6.5.5 Reading Python Source Files 329
6.6 tempfile: Temporary File System Objects 330
6.6.1 Temporary Files 331
6.6.2 Named Files 333
6.6.3 Spooled Files 333
6.6.4 Temporary Directories 335
6.6.5 Predicting Names 335
6.6.6 Temporary File Location 336
6.7 shutil: High-Level File Operations 337
6.7.1 Copying Files 337
6.7.2 Copying File Metadata 340
6.7.3 Working with Directory Trees 342
6.7.4 Finding Files 345
6.7.5 Archives 346
6.7.6 File System Space 350
6.8 filecmp: Compare Files 351
6.8.1 Example Data 351
6.8.2 Comparing Files 353
6.8.3 Comparing Directories 355
6.8.4 Using Differences in a Program 357
6.9 mmap: Memory-Map Files 361
6.9.1 Reading 361
6.9.2 Writing 362
6.9.3 Regular Expressions 364
6.10 codecs: String Encoding and Decoding 365
6.10.1 Unicode Primer 365
6.10.2 Working with Files 368
6.10.3 Byte Order 370
6.10.4 Error Handling 372
6.10.5 Encoding Translation 376
6.10.6 Non-Unicode Encodings 377
6.10.7 Incremental Encoding 378
6.10.8 Unicode Data and Network Communication 380
6.10.9 Defining a Custom Encoding 383
6.11 io: Text, Binary, and Raw Stream I/O Tools 390
6.11.1 In-Memory Streams 390
6.11.2 Wrapping Byte Streams for Text Data 392
Contents xv

Chapter 7 Data Persistence and Exchange 395


7.1 pickle: Object Serialization 396
7.1.1 Encoding and Decoding Data in Strings 396
7.1.2 Working with Streams 397
7.1.3 Problems Reconstructing Objects 399
7.1.4 Unpicklable Objects 400
7.1.5 Circular References 402
7.2 shelve: Persistent Storage of Objects 405
7.2.1 Creating a New Shelf 405
7.2.2 Writeback 406
7.2.3 Specific Shelf Types 408
7.3 dbm: Unix Key–Value Databases 408
7.3.1 Database Types 408
7.3.2 Creating a New Database 409
7.3.3 Opening an Existing Database 410
7.3.4 Error Cases 411
7.4 sqlite3: Embedded Relational Database 412
7.4.1 Creating a Database 412
7.4.2 Retrieving Data 415
7.4.3 Query Metadata 417
7.4.4 Row Objects 417
7.4.5 Using Variables with Queries 419
7.4.6 Bulk Loading 421
7.4.7 Defining New Column Types 422
7.4.8 Determining Types for Columns 426
7.4.9 Transactions 428
7.4.10 Isolation Levels 431
7.4.11 In-Memory Databases 434
7.4.12 Exporting the Contents of a Database 435
7.4.13 Using Python Functions in SQL 436
7.4.14 Querying with Regular Expressions 439
7.4.15 Custom Aggregation 440
7.4.16 Threading and Connection Sharing 441
7.4.17 Restricting Access to Data 442
7.5 xml.etree.ElementTree: XML Manipulation API 445
7.5.1 Parsing an XML Document 445
7.5.2 Traversing the Parsed Tree 446
7.5.3 Finding Nodes in a Document 447
7.5.4 Parsed Node Attributes 449
7.5.5 Watching Events While Parsing 451
7.5.6 Creating a Custom Tree Builder 453
7.5.7 Parsing Strings 455
7.5.8 Building Documents With Element Nodes 457
7.5.9 Pretty-Printing XML 458
7.5.10 Setting Element Properties 459
xvi Contents

7.5.11 Building Trees from Lists of Nodes 461


7.5.12 Serializing XML to a Stream 464
7.6 csv: Comma-Separated Value Files 466
7.6.1 Reading 466
7.6.2 Writing 467
7.6.3 Dialects 469
7.6.4 Using Field Names 474

Chapter 8 Data Compression and Archiving 477


8.1 zlib: GNU zlib Compression 477
8.1.1 Working with Data in Memory 477
8.1.2 Incremental Compression and Decompression 479
8.1.3 Mixed Content Streams 480
8.1.4 Checksums 481
8.1.5 Compressing Network Data 482
8.2 gzip: Read and Write GNU zip Files 486
8.2.1 Writing Compressed Files 486
8.2.2 Reading Compressed Data 489
8.2.3 Working with Streams 490
8.3 bz2: bzip2 Compression 491
8.3.1 One-Shot Operations in Memory 492
8.3.2 Incremental Compression and Decompression 493
8.3.3 Mixed-Content Streams 494
8.3.4 Writing Compressed Files 495
8.3.5 Reading Compressed Files 497
8.3.6 Reading and Writing Unicode Data 498
8.3.7 Compressing Network Data 499
8.4 tarfile: Tar Archive Access 503
8.4.1 Testing Tar Files 503
8.4.2 Reading Metadata from an Archive 504
8.4.3 Extracting Files from an Archive 506
8.4.4 Creating New Archives 508
8.4.5 Using Alternative Archive Member Names 508
8.4.6 Writing Data from Sources Other Than Files 509
8.4.7 Appending to Archives 510
8.4.8 Working with Compressed Archives 510
8.5 zipfile: ZIP Archive Access 511
8.5.1 Testing ZIP Files 512
8.5.2 Reading Metadata from an Archive 512
8.5.3 Extracting Archived Files From an Archive 514
8.5.4 Creating New Archives 514
8.5.5 Using Alternative Archive Member Names 516
8.5.6 Writing Data from Sources Other Than Files 517
8.5.7 Writing with a ZipInfo Instance 517
8.5.8 Appending to Files 518
Contents xvii

8.5.9 Python ZIP Archives 519


8.5.10 Limitations 521

Chapter 9 Cryptography 523


9.1 hashlib: Cryptographic Hashing 523
9.1.1 Hash Algorithms 523
9.1.2 Sample Data 524
9.1.3 MD5 Example 524
9.1.4 SHA1 Example 525
9.1.5 Creating a Hash by Name 525
9.1.6 Incremental Updates 526
9.2 hmac: Cryptographic Message Signing and Verification 528
9.2.1 Signing Messages 528
9.2.2 Alternative Digest Types 528
9.2.3 Binary Digests 529
9.2.4 Applications of Message Signatures 530

Chapter 10 Concurrency with Processes, Threads, and Coroutines 535


10.1 subprocess: Spawning Additional Processes 535
10.1.1 Running External Command 536
10.1.2 Working with Pipes Directly 542
10.1.3 Connecting Segments of a Pipe 545
10.1.4 Interacting with Another Command 546
10.1.5 Signaling Between Processes 548
10.2 signal: Asynchronous System Events 553
10.2.1 Receiving Signals 554
10.2.2 Retrieving Registered Handlers 555
10.2.3 Sending Signals 556
10.2.4 Alarms 556
10.2.5 Ignoring Signals 557
10.2.6 Signals and Threads 558
10.3 threading: Manage Concurrent Operations Within a Process 560
10.3.1 Thread Objects 560
10.3.2 Determining the Current Thread 562
10.3.3 Daemon Versus Non-daemon Threads 564
10.3.4 Enumerating All Threads 567
10.3.5 Subclassing Thread 568
10.3.6 Timer Threads 570
10.3.7 Signaling Between Threads 571
10.3.8 Controlling Access to Resources 572
10.3.9 Synchronizing Threads 578
10.3.10 Limiting Concurrent Access to Resources 581
10.3.11 Thread Specific Data 583
10.4 multiprocessing: Manage Processes Like Threads 586
10.4.1 multiprocessing Basics 586
10.4.2 Importable Target Functions 587
xviii Contents

10.4.3 Determining the Current Process 588


10.4.4 Daemon Processes 589
10.4.5 Waiting for Processes 591
10.4.6 Terminating Processes 593
10.4.7 Process Exit Status 594
10.4.8 Logging 596
10.4.9 Subclassing Process 597
10.4.10 Passing Messages to Processes 598
10.4.11 Signaling Between Processes 602
10.4.12 Controlling Access to Resources 603
10.4.13 Synchronizing Operations 604
10.4.14 Controlling Concurrent Access to Resources 605
10.4.15 Managing Shared State 608
10.4.16 Shared Namespaces 608
10.4.17 Process Pools 611
10.4.18 Implementing MapReduce 613
10.5 asyncio: Asynchronous I/O, Event Loop, and Concurrency Tools 617
10.5.1 Asynchronous Concurrency Concepts 618
10.5.2 Cooperative Multitasking with Coroutines 618
10.5.3 Scheduling Calls to Regular Functions 622
10.5.4 Producing Results Asynchronously 625
10.5.5 Executing Tasks Concurrently 628
10.5.6 Composing Coroutines with Control Structures 632
10.5.7 Synchronization Primitives 637
10.5.8 Asynchronous I/O with Protocol Class Abstractions 644
10.5.9 Asynchronous I/O Using Coroutines and Streams 650
10.5.10 Using SSL 656
10.5.11 Interacting with Domain Name Services 658
10.5.12 Working with Subprocesses 661
10.5.13 Receiving Unix Signals 668
10.5.14 Combining Coroutines with Threads and Processes 670
10.5.15 Debugging with asyncio 673
10.6 concurrent.futures: Manage Pools of Concurrent Tasks 677
10.6.1 Using map() with a Basic Thread Pool 677
10.6.2 Scheduling Individual Tasks 678
10.6.3 Waiting for Tasks in Any Order 679
10.6.4 Future Callbacks 680
10.6.5 Canceling Tasks 681
10.6.6 Exceptions in Tasks 683
10.6.7 Context Manager 683
10.6.8 Process Pools 684
Contents xix

Chapter 11 Networking 687


11.1 ipaddress: Internet Addresses 687
11.1.1 Addresses 687
11.1.2 Networks 688
11.1.3 Interfaces 692
11.2 socket: Network Communication 693
11.2.1 Addressing, Protocol Families, and Socket Types 693
11.2.2 TCP/IP Client and Server 704
11.2.3 User Datagram Client and Server 711
11.2.4 Unix Domain Sockets 714
11.2.5 Multicast 717
11.2.6 Sending Binary Data 721
11.2.7 Non-blocking Communication and Timeouts 723
11.3 selectors: I/O Multiplexing Abstractions 724
11.3.1 Operating Model 724
11.3.2 Echo Server 724
11.3.3 Echo Client 726
11.3.4 Server and Client Together 727
11.4 select: Wait for I/O Efficiently 728
11.4.1 Using select() 729
11.4.2 Non-blocking I/O with Timeouts 734
11.4.3 Using poll() 737
11.4.4 Platform-Specific Options 742
11.5 socketserver: Creating Network Servers 742
11.5.1 Server Types 742
11.5.2 Server Objects 743
11.5.3 Implementing a Server 743
11.5.4 Request Handlers 743
11.5.5 Echo Example 744
11.5.6 Threading and Forking 749

Chapter 12 The Internet 753


12.1 urllib.parse: Split URLs into Components 753
12.1.1 Parsing 754
12.1.2 Unparsing 756
12.1.3 Joining 758
12.1.4 Encoding Query Arguments 759
12.2 urllib.request: Network Resource Access 761
12.2.1 HTTP GET 761
12.2.2 Encoding Arguments 763
12.2.3 HTTP POST 764
12.2.4 Adding Outgoing Headers 765
12.2.5 Posting Form Data from a Request 766
12.2.6 Uploading Files 767
12.2.7 Creating Custom Protocol Handlers 770
xx Contents

12.3 urllib.robotparser: Internet Spider Access Control 773


12.3.1 robots.txt 773
12.3.2 Testing Access Permissions 774
12.3.3 Long-Lived Spiders 775
12.4 base64: Encode Binary Data with ASCII 776
12.4.1 Base 64 Encoding 777
12.4.2 Base64 Decoding 778
12.4.3 URL-Safe Variations 778
12.4.4 Other Encodings 779
12.5 http.server: Base Classes for Implementing Web Servers 781
12.5.1 HTTP GET 781
12.5.2 HTTP POST 784
12.5.3 Threading and Forking 786
12.5.4 Handling Errors 787
12.5.5 Setting Headers 788
12.5.6 Command-Line Use 789
12.6 http.cookies: HTTP Cookies 790
12.6.1 Creating and Setting a Cookie 790
12.6.2 Morsels 791
12.6.3 Encoded Values 793
12.6.4 Receiving and Parsing Cookie Headers 794
12.6.5 Alternative Output Formats 795
12.7 webbrowser: Displays Web Pages 796
12.7.1 Simple Example 796
12.7.2 Windows Versus Tabs 796
12.7.3 Using a Specific Browser 796
12.7.4 BROWSER Variable 797
12.7.5 Command-Line Interface 797
12.8 uuid: Universally Unique Identifiers 797
12.8.1 UUID 1: IEEE 802 MAC Address 798
12.8.2 UUID 3 and 5: Name-Based Values 800
12.8.3 UUID 4: Random Values 802
12.8.4 Working with UUID Objects 802
12.9 json: JavaScript Object Notation 803
12.9.1 Encoding and Decoding Simple Data Types 804
12.9.2 Human-Consumable Versus Compact Output 805
12.9.3 Encoding Dictionaries 807
12.9.4 Working with Custom Types 807
12.9.5 Encoder and Decoder Classes 810
12.9.6 Working with Streams and Files 813
12.9.7 Mixed Data Streams 813
12.9.8 JSON at the Command Line 815
12.10 xmlrpc.client: Client Library for XML-RPC 816
12.10.1 Connecting to a Server 817
12.10.2 Data Types 819
Contents xxi

12.10.3 Passing Objects 822


12.10.4 Binary Data 823
12.10.5 Exception Handling 825
12.10.6 Combining Calls into One Message 826
12.11 xmlrpc.server: An XML-RPC Server 827
12.11.1 A Simple Server 828
12.11.2 Alternate API Names 829
12.11.3 Dotted API Names 830
12.11.4 Arbitrary API Names 831
12.11.5 Exposing Methods of Objects 832
12.11.6 Dispatching Calls 834
12.11.7 Introspection API 837

Chapter 13 Email 841


13.1 smtplib: Simple Mail Transfer Protocol Client 841
13.1.1 Sending an Email Message 841
13.1.2 Authentication and Encryption 843
13.1.3 Verifying an Email Address 846
13.2 smtpd: Sample Mail Servers 847
13.2.1 Mail Server Base Class 847
13.2.2 Debugging Server 850
13.2.3 Proxy Server 851
13.3 mailbox: Manipulate Email Archives 852
13.3.1 mbox 852
13.3.2 Maildir 855
13.3.3 Message Flags 862
13.3.4 Other Formats 864
13.4 imaplib: IMAP4 Client Library 864
13.4.1 Variations 864
13.4.2 Connecting to a Server 864
13.4.3 Example Configuration 866
13.4.4 Listing Mailboxes 866
13.4.5 Mailbox Status 869
13.4.6 Selecting a Mailbox 871
13.4.7 Searching for Messages 872
13.4.8 Search Criteria 872
13.4.9 Fetching Messages 874
13.4.10 Whole Messages 880
13.4.11 Uploading Messages 881
13.4.12 Moving and Copying Messages 883
13.4.13 Deleting Messages 884
xxii Contents

Chapter 14 Application Building Blocks 887


14.1 argparse: Command-Line Option and Argument Parsing 888
14.1.1 Setting Up a Parser 888
14.1.2 Defining Arguments 888
14.1.3 Parsing a Command Line 889
14.1.4 Simple Examples 889
14.1.5 Help Output 897
14.1.6 Parser Organization 901
14.1.7 Advanced Argument Processing 908
14.2 getopt: Command-Line Option Parsing 916
14.2.1 Function Arguments 916
14.2.2 Short-Form Options 917
14.2.3 Long-Form Options 917
14.2.4 A Complete Example 918
14.2.5 Abbreviating Long-Form Options 920
14.2.6 GNU-Style Option Parsing 920
14.2.7 Ending Argument Processing 922
14.3 readline: The GNU readline Library 922
14.3.1 Configuring readline 923
14.3.2 Completing Text 924
14.3.3 Accessing the Completion Buffer 927
14.3.4 Input History 931
14.3.5 Hooks 934
14.4 getpass: Secure Password Prompt 935
14.4.1 Example 935
14.4.2 Using getpass Without a Terminal 937
14.5 cmd: Line-Oriented Command Processors 938
14.5.1 Processing Commands 938
14.5.2 Command Arguments 940
14.5.3 Live Help 941
14.5.4 Auto-Completion 942
14.5.5 Overriding Base Class Methods 944
14.5.6 Configuring Cmd Through Attributes 946
14.5.7 Running Shell Commands 947
14.5.8 Alternative Inputs 948
14.5.9 Commands from sys.argv 950
14.6 shlex: Parse Shell-Style Syntaxes 951
14.6.1 Parsing Quoted Strings 951
14.6.2 Making Safe Strings for Shells 953
14.6.3 Embedded Comments 954
14.6.4 Splitting Strings into Tokens 954
14.6.5 Including Other Sources of Tokens 955
14.6.6 Controlling the Parser 956
14.6.7 Error Handling 957
14.6.8 POSIX Versus Non-POSIX Parsing 959
Contents xxiii

14.7 configparser: Work with Configuration Files 960


14.7.1 Configuration File Format 961
14.7.2 Reading Configuration Files 961
14.7.3 Accessing Configuration Settings 963
14.7.4 Modifying Settings 970
14.7.5 Saving Configuration Files 972
14.7.6 Option Search Path 972
14.7.7 Combining Values with Interpolation 975
14.8 logging: Report Status, Error, and Informational Messages 980
14.8.1 Logging Components 980
14.8.2 Logging in Applications Versus Libraries 980
14.8.3 Logging to a File 981
14.8.4 Rotating Log Files 981
14.8.5 Verbosity Levels 982
14.8.6 Naming Logger Instances 984
14.8.7 The Logging Tree 984
14.8.8 Integration with the warnings Module 985
14.9 fileinput: Command-Line Filter Framework 986
14.9.1 Converting M3U Files to RSS 987
14.9.2 Progress Metadata 989
14.9.3 In-Place Filtering 990
14.10 atexit: Program Shutdown Callbacks 993
14.10.1 Registering Exit Callbacks 993
14.10.2 Decorator Syntax 994
14.10.3 Canceling Callbacks 994
14.10.4 When Are atexit Callbacks Not Called? 995
14.10.5 Handling Exceptions 997
14.11 sched: Timed Event Scheduler 998
14.11.1 Running Events with a Delay 999
14.11.2 Overlapping Events 1000
14.11.3 Event Priorities 1001
14.11.4 Canceling Events 1001

Chapter 15 Internationalization and Localization 1003


15.1 gettext: Message Catalogs 1003
15.1.1 Translation Workflow Overview 1003
15.1.2 Creating Message Catalogs from Source Code 1004
15.1.3 Finding Message Catalogs at Runtime 1007
15.1.4 Plural Values 1008
15.1.5 Application Versus Module Localization 1011
15.1.6 Switching Translations 1012
15.2 locale: Cultural Localization API 1012
15.2.1 Probing the Current Locale 1013
15.2.2 Currency 1018
15.2.3 Formatting Numbers 1019
xxiv Contents

15.2.4 Parsing Numbers 1021


15.2.5 Dates and Times 1022

Chapter 16 Developer Tools 1023


16.1 pydoc: Online Help for Modules 1024
16.1.1 Plain Text Help 1024
16.1.2 HTML Help 1025
16.1.3 Interactive Help 1026
16.2 doctest: Testing Through Documentation 1026
16.2.1 Getting Started 1026
16.2.2 Handling Unpredictable Output 1028
16.2.3 Tracebacks 1032
16.2.4 Working Around Whitespace 1034
16.2.5 Test Locations 1039
16.2.6 External Documentation 1042
16.2.7 Running Tests 1044
16.2.8 Test Context 1048
16.3 unittest: Automated Testing Framework 1051
16.3.1 Basic Test Structure 1051
16.3.2 Running Tests 1051
16.3.3 Test Outcomes 1052
16.3.4 Asserting Truth 1054
16.3.5 Testing Equality 1054
16.3.6 Almost Equal? 1055
16.3.7 Containers 1056
16.3.8 Testing for Exceptions 1061
16.3.9 Test Fixtures 1062
16.3.10 Repeating Tests with Different Inputs 1065
16.3.11 Skipping Tests 1066
16.3.12 Ignoring Failing Tests 1068
16.4 trace: Follow Program Flow 1069
16.4.1 Example Program 1069
16.4.2 Tracing Execution 1069
16.4.3 Code Coverage 1070
16.4.4 Calling Relationships 1073
16.4.5 Programming Interface 1074
16.4.6 Saving Result Data 1076
16.4.7 Options 1077
16.5 traceback: Exceptions and Stack Traces 1078
16.5.1 Supporting Functions 1079
16.5.2 Examining the Stack 1079
16.5.3 TracebackException 1081
16.5.4 Low-Level Exception APIs 1082
16.5.5 Low-Level Stack APIs 1086
Contents xxv

16.6 cgitb: Detailed Traceback Reports 1089


16.6.1 Standard Traceback Dumps 1089
16.6.2 Enabling Detailed Tracebacks 1090
16.6.3 Local Variables in Tracebacks 1093
16.6.4 Exception Properties 1096
16.6.5 HTML Output 1098
16.6.6 Logging Tracebacks 1098
16.7 pdb: Interactive Debugger 1101
16.7.1 Starting the Debugger 1101
16.7.2 Controlling the Debugger 1104
16.7.3 Breakpoints 1117
16.7.4 Changing Execution Flow 1129
16.7.5 Customizing the Debugger with Aliases 1136
16.7.6 Saving Configuration Settings 1137
16.8 profile and pstats: Performance Analysis 1140
16.8.1 Running the Profiler 1140
16.8.2 Running in a Context 1143
16.8.3 pstats: Saving and Working with Statistics 1144
16.8.4 Limiting Report Contents 1145
16.8.5 Caller/Callee Graphs 1146
16.9 timeit: Time the Execution of Small Bits of Python Code 1148
16.9.1 Module Contents 1148
16.9.2 Basic Example 1148
16.9.3 Storing Values in a Dictionary 1149
16.9.4 From the Command Line 1152
16.10 tabnanny: Indentation Validator 1153
16.10.1 Running from the Command Line 1153
16.11 compileall: Byte-Compile Source Files 1155
16.11.1 Compiling One Directory 1155
16.11.2 Ignoring Files 1156
16.11.3 Compiling sys.path 1157
16.11.4 Compiling Individual Files 1157
16.11.5 From the Command Line 1158
16.12 pyclbr: Class Browser 1160
16.12.1 Scanning for Classes 1161
16.12.2 Scanning for Functions 1162
16.13 venv: Create Virtual Environments 1163
16.13.1 Creating Environments 1163
16.13.2 Contents of a Virtual Environment 1164
16.13.3 Using Virtual Environments 1165
16.14 ensurepip: Install the Python Package Installer 1167
16.14.1 Installing pip 1167
xxvi Contents

Chapter 17 Runtime Features 1169


17.1 site: Site-wide Configuration 1169
17.1.1 Import Path 1169
17.1.2 User Directories 1171
17.1.3 Path Configuration Files 1172
17.1.4 Customizing Site Configuration 1175
17.1.5 Customizing User Configuration 1176
17.1.6 Disabling the site Module 1177
17.2 sys: System-Specific Configuration 1178
17.2.1 Interpreter Settings 1178
17.2.2 Runtime Environment 1185
17.2.3 Memory Management and Limits 1187
17.2.4 Exception Handling 1194
17.2.5 Low-Level Thread Support 1197
17.2.6 Modules and Imports 1200
17.2.7 Tracing a Program As It Runs 1221
17.3 os: Portable Access to Operating System–Specific Features 1227
17.3.1 Examining the File System Contents 1228
17.3.2 Managing File System Permissions 1230
17.3.3 Creating and Deleting Directories 1233
17.3.4 Working with Symbolic Links 1234
17.3.5 Safely Replacing an Existing File 1234
17.3.6 Detecting and Changing the Process Owner 1235
17.3.7 Managing the Process Environment 1237
17.3.8 Managing the Process Working Directory 1238
17.3.9 Running External Commands 1239
17.3.10 Creating Processes with os.fork() 1240
17.3.11 Waiting for Child Processes 1242
17.3.12 Spawning New Processes 1244
17.3.13 Operating System Error Codes 1245
17.4 platform: System Version Information 1246
17.4.1 Interpreter 1246
17.4.2 Platform 1247
17.4.3 Operating System and Hardware Information 1248
17.4.4 Executable Architecture 1250
17.5 resource: System Resource Management 1251
17.5.1 Current Usage 1251
17.5.2 Resource Limits 1252
17.6 gc: Garbage Collector 1254
17.6.1 Tracing References 1255
17.6.2 Forcing Garbage Collection 1258
17.6.3 Finding References to Objects That Cannot Be Collected 1259
17.6.4 Collection Thresholds and Generations 1261
17.6.5 Debugging 1265
Contents xxvii

17.7 sysconfig: Interpreter Compile-Time Configuration 1270


17.7.1 Configuration Variables 1270
17.7.2 Installation Paths 1272
17.7.3 Python Version and Platform 1276

Chapter 18 Language Tools 1279


18.1 warnings: Non-fatal Alerts 1279
18.1.1 Categories and Filtering 1280
18.1.2 Generating Warnings 1280
18.1.3 Filtering with Patterns 1281
18.1.4 Repeated Warnings 1283
18.1.5 Alternative Message Delivery Functions 1284
18.1.6 Formatting 1285
18.1.7 Stack Level in Warnings 1286
18.2 abc: Abstract Base Classes 1287
18.2.1 How ABCs Work 1287
18.2.2 Registering a Concrete Class 1287
18.2.3 Implementation Through Subclassing 1288
18.2.4 Helper Base Class 1289
18.2.5 Incomplete Implementations 1290
18.2.6 Concrete Methods in ABCs 1291
18.2.7 Abstract Properties 1292
18.2.8 Abstract Class and Static Methods 1295
18.3 dis: Python Byte-Code Disassembler 1296
18.3.1 Basic Disassembly 1297
18.3.2 Disassembling Functions 1297
18.3.3 Classes 1300
18.3.4 Source Code 1301
18.3.5 Using Disassembly to Debug 1302
18.3.6 Performance Analysis of Loops 1303
18.3.7 Compiler Optimizations 1309
18.4 inspect: Inspect Live Objects 1311
18.4.1 Example Module 1311
18.4.2 Inspecting Modules 1312
18.4.3 Inspecting Classes 1314
18.4.4 Inspecting Instances 1316
18.4.5 Documentation Strings 1316
18.4.6 Retrieving Source 1318
18.4.7 Method and Function Signatures 1319
18.4.8 Class Hierarchies 1322
18.4.9 Method Resolution Order 1323
18.4.10 The Stack and Frames 1324
18.4.11 Command-Line Interface 1327
xxviii Contents

Chapter 19 Modules and Packages 1329


19.1 importlib: Python’s Import Mechanism 1329
19.1.1 Example Package 1329
19.1.2 Module Types 1330
19.1.3 Importing Modules 1331
19.1.4 Loaders 1332
19.2 pkgutil: Package Utilities 1334
19.2.1 Package Import Paths 1334
19.2.2 Development Versions of Packages 1336
19.2.3 Managing Paths with PKG Files 1338
19.2.4 Nested Packages 1340
19.2.5 Package Data 1341
19.3 zipimport: Load Python Code from ZIP Archives 1344
19.3.1 Example 1344
19.3.2 Finding a Module 1345
19.3.3 Accessing Code 1345
19.3.4 Source 1346
19.3.5 Packages 1348
19.3.6 Data 1348

Appendix A Porting Notes 1351


A.1 References 1351
A.2 New Modules 1352
A.3 Renamed Modules 1352
A.4 Removed Modules 1354
A.4.1 bsddb 1354
A.4.2 commands 1354
A.4.3 compiler 1354
A.4.4 dircache 1354
A.4.5 EasyDialogs 1354
A.4.6 exceptions 1354
A.4.7 htmllib 1354
A.4.8 md5 1354
A.4.9 mimetools, MimeWriter, mimify, multifile, and rfc822 1354
A.4.10 popen2 1354
A.4.11 posixfile 1355
A.4.12 sets 1355
A.4.13 sha 1355
A.4.14 sre 1355
A.4.15 statvfs 1355
A.4.16 thread 1355
A.4.17 user 1355
A.5 Deprecated Modules 1355
A.5.1 asyncore and asynchat 1355
A.5.2 formatter 1355
Contents xxix

A.5.3 imp 1356


A.5.4 optparse 1356
A.6 Summary of Changes to Modules 1356
A.6.1 abc 1356
A.6.2 anydbm 1356
A.6.3 argparse 1356
A.6.4 array 1357
A.6.5 atexit 1357
A.6.6 base64 1357
A.6.7 bz2 1357
A.6.8 collections 1357
A.6.9 comands 1357
A.6.10 configparser 1358
A.6.11 contextlib 1358
A.6.12 csv 1358
A.6.13 datetime 1358
A.6.14 decimal 1358
A.6.15 fractions 1358
A.6.16 gc 1358
A.6.17 gettext 1359
A.6.18 glob 1359
A.6.19 http.cookies 1359
A.6.20 imaplib 1359
A.6.21 inspect 1359
A.6.22 itertools 1359
A.6.23 json 1359
A.6.24 locale 1359
A.6.25 logging 1360
A.6.26 mailbox 1360
A.6.27 mmap 1360
A.6.28 operator 1360
A.6.29 os 1360
A.6.30 os.path 1361
A.6.31 pdb 1361
A.6.32 pickle 1361
A.6.33 pipes 1362
A.6.34 platform 1362
A.6.35 random 1362
A.6.36 re 1362
A.6.37 shelve 1362
A.6.38 signal 1362
A.6.39 socket 1362
A.6.40 socketserver 1363
A.6.41 string 1363
A.6.42 struct 1363
xxx Contents

A.6.43 subprocess 1363


A.6.44 sys 1363
A.6.45 threading 1364
A.6.46 time 1364
A.6.47 unittest 1364
A.6.48 UserDict, UserList, and UserString 1365
A.6.49 uuid 1365
A.6.50 whichdb 1365
A.6.51 xml.etree.ElementTree 1365
A.6.52 zipimport 1365

Appendix B Outside of the Standard Library 1367


B.1 Text 1367
B.2 Algorithms 1367
B.3 Dates and Times 1368
B.4 Mathematics 1368
B.5 Data Persistence and Exchange 1368
B.6 Cryptography 1369
B.7 Concurrency with Processes, Threads, and Coroutines 1369
B.8 The Internet 1369
B.9 Email 1370
B.10 Application Building Blocks 1370
B.11 Developer Tools 1371

Index of Python Modules 1373

Index 1375
Introduction
Distributed with every copy of Python, the standard library contains hundreds of modules
that provide tools for interacting with the operating system, interpreter, and Internet—all
of them tested and ready to be used to jump-start the development of your applications.
This book presents selected examples demonstrating how to use the most commonly used
features of the modules that support Python’s “batteries included” slogan, taken from the
popular Python Module of the Week (PyMOTW) blog series.

This Book’s Target Audience


The audience for this book consists of intermediate-level Python programmers. Thus,
although all of the source code is presented with discussion, only a few cases include line-
by-line explanations. Every section focuses on the features of the modules, illustrated by
the source code and output from fully independent example programs. Each feature is
presented as concisely as possible, so the reader can focus on the module or function being
demonstrated without being distracted by the supporting code.
An experienced programmer who is familiar with other languages may be able to learn
Python from this book, but the text is not intended to be an introduction to the language.
Some prior experience writing Python programs will be useful when studying the examples.
Several sections, such as the description of network programming with sockets or hmac
encryption, require domain-specific knowledge. The basic information needed to explain the
examples is included here, but the range of topics covered by the modules in the standard
library makes it impossible to cover every topic comprehensively in a single volume. The
discussion of each module is followed by a list of suggested sources for more information and
further reading, including online resources, RFC standards documents, and related books.

Python 3 Versus 2
The Python community is currently undergoing a transition from Python version 2 to
Python version 3. As the major version number change implies, there are many incompati-
bilities between Python 2 and 3, and not just in the language. Quite a few of the standard
library modules have been renamed or otherwise reorganized in Python 3.
The Python development community recognized that those incompatibilities would
require an extended transition period, while the ecosystem of Python libraries and tools
was updated to work with Python 3. Although many projects still rely on Python 2, it is
xxxi
xxxii Introduction

only receiving security updates and is scheduled to be completely deprecated by 2020. All
new-feature work is happening in the Python 3 releases.
It can be challenging, though not impossible, to write programs that work with both
versions. Doing so often requires examining the version of Python under which a program
is running and using different module names for imports or different arguments to classes
or functions. A variety of tools, available outside of the standard library, can simplify this
process. To keep the examples in this book as concise as possible, while still relying only on
the standard library, they are focused on Python 3. All of the examples have been tested
under Python 3.5 (the current release of the 3.x series at the time they were written), and
may not work with Python 2 without modification. For examples designed to work with
Python 2, refer to the Python 2 edition of the book, called The Python Standard Library
by Example.
In an effort to maintain clear and concise descriptions for each example, the differences
between Python 2 and 3 are not highlighted in each chapter. The Porting Notes appendix
summarizes some of the biggest differences between these versions, and is organized to be
useful as an aid when porting from Python 2 to 3.

How This Book Is Organized


This book supplements the comprehensive reference guide (available at http://docs
.python.org), providing fully functional example programs to demonstrate the features
described there. The modules are grouped into chapters to make it easy to find an indi-
vidual module for reference and browse by subject for more leisurely exploration. In the
unlikely event that you want to read it through from cover to cover, it is organized to
minimize “forward references” to modules not yet covered, although it was not possible to
eliminate them entirely.

Downloading the Example Code


The original versions of the articles and the sample code are available at https://
pymotw.com/3/. Errata for the book can be found on the author’s website:
https://doughellmann.com/blog/the-python-3-standard-library-by-example/.

Register your copy of The Python 3 Standard Library by Example at informit.com for
convenient access to downloads, updates, and corrections as they become available. To
start the registration process, go to informit.com/register and log in or create an account.
Enter the product ISBN (9780134291055) and click Submit. Once the process is complete,
you will find any available bonus content under “Registered Products.”
Acknowledgments
This book would not have come into being without the contributions and support of many
other people.
I was first introduced to Python around 1997 by Dick Wall, while we were working
together on GIS software at ERDAS. I remember being simultaneously happy that I had
found a new tool language that was so easy to use, and sad that the company did not let
us use it for “real work.” I have used Python extensively at all of my subsequent jobs, and I
have Dick to thank for the many happy hours I have spent working on software since then.
The Python core development team has created a robust ecosystem of language, tools,
and libraries that continue to grow in popularity and find new application areas. Without
the continued investment in time and resources they have given us, we would all still be
spending our energy reinventing wheel after wheel.
The material in this book started out as a series of blog posts. Without the exceptionally
positive response of the readers of the blog, those articles would never have been updated
to work with Python 3, and this new book would not exist. Each of those posts has been
reviewed and commented on by members of the Python community, with corrections, sug-
gestions, and questions that led to the refinements and improvements that appear in this
book. Thank you all for reading along week after week, and contributing your time and
attention.
The technical reviewers for the book—Diana Clarke, Ian Cordasco, Mark McClain, Paul
McLanahan, and Ryan Petrello—spent many hours looking for issues with the example code
and accompanying explanations. Thanks to their diligence, the resulting text is stronger
than I could have produced on my own.
Jim Baker provided helpful insight when documenting the readline module, especially
by pointing out the gnureadline package for platforms where GNU libraries are old or not
installed by default.
Patrick Kettner helped to collect the output for the platform module examples on
Windows.
A special thanks goes to the editors, production staff, and marketing team at Addison-
Wesley for all of their hard work and assistance in helping me realize my vision for this
book and make it a success.
Finally, I want to thank my wife, Theresa Flynn, who has gracefully accepted all of the
lost nights and weekends over the course of this new project. Thank you for your advice,
encouragement, and support.

xxxiii
This page intentionally left blank
About the Author
Doug Hellmann is currently employed by Red Hat to work
on OpenStack. He is on the OpenStack Technical Committee
and contributes to many aspects of the project. He has been
programming in Python since version 1.4, and has worked on
a variety of Unix and non-Unix platforms for projects in fields
such as mapping, medical news publishing, banking, and data
center automation. Doug is a Fellow of the Python Software
Foundation, and served as its Communications Director from
2010 to 2012. After a year as a regular columnist for Python
Magazine, he served as Editor-in-Chief from 2008 to 2009.
Between 2007 and 2011, Doug published the popular Python Module of the Week series
on his blog, and an earlier version of this book for Python 2 called The Python Standard
Library by Example. He lives in Athens, Georgia.

xxxv
This page intentionally left blank
Chapter 1
Text
The str class is the most obvious text processing tool available to Python programmers, but
there are plenty of other tools in the standard library to make advanced text manipulation
simple.
Programs may use string.Template as a simple way to parameterize strings beyond
the features of str objects. While not as feature-rich as templates defined by many of
the web frameworks or extension modules available from the Python Package Index,
string.Template is a good middle ground for user-modifiable templates in which dynamic
values need to be inserted into otherwise static text.
The textwrap (page 7) module includes tools for formatting text from paragraphs by
limiting the width of output, adding indentation, and inserting line breaks to wrap lines
consistently.
The standard library includes two modules for comparing text values that go beyond
the built-in equality and sort comparison supported by string objects. re (page 13) provides
a complete regular expression library, implemented in C for speed. Regular expressions
are well suited for finding substrings within a larger data set, comparing strings against a
pattern more complex than another fixed string, and mild parsing.
difflib (page 58), in contrast, computes the actual differences between sequences of text
in terms of the parts added, removed, or changed. The output of the comparison functions
in difflib can be used to provide more detailed feedback to the user about where changes
occur in two inputs, how a document has changed over time, and so on.

1.1 string: Text Constants and Templates


The string module dates from the earliest versions of Python. Many of the functions pre-
viously implemented in the module have been moved to methods of str objects, but the
module retains several useful constants and classes for working with str objects. This dis-
cussion will concentrate on them.

1.1.1 Functions
The function capwords() capitalizes all of the words in a string.

Listing 1.1: string_capwords.py


import string

s = 'The quick brown fox jumped over the lazy dog.'

1
2 Chapter 1 Text

print(s)
print(string.capwords(s))

The results are the same as those obtained by calling split(), capitalizing the words in
the resulting list, and then calling join() to combine the results.

$ python3 string_capwords.py

The quick brown fox jumped over the lazy dog.


The Quick Brown Fox Jumped Over The Lazy Dog.

1.1.2 Templates
String templates were added as part of PEP 2921 and are intended as an alternative to the
built-in interpolation syntax. With string.Template interpolation, variables are identified
by prefixing the name with $ (e.g., $var). Alternatively, if necessary to set them off from
surrounding text, they can be wrapped with curly braces (e.g., ${var}).
This example compares a simple template with similar string interpolation using the %
operator and the new format string syntax using str.format().

Listing 1.2: string_template.py


import string

values = {'var': 'foo'}

t = string.Template("""
Variable : $var
Escape : $$
Variable in text: ${var}iable
""")

print('TEMPLATE:', t.substitute(values))

s = """
Variable : %(var)s
Escape : %%
Variable in text: %(var)siable
"""

print('INTERPOLATION:', s % values)

s = """
Variable : {var}
Escape : {{}}

1 www.python.org/dev/peps/pep-0292
1.1 string: Text Constants and Templates 3

Variable in text: {var}iable


"""

print('FORMAT:', s.format(**values))

In the first two cases, the trigger character ($ or %) is escaped by repeating it twice. For the
format syntax, both { and } need to be escaped by repeating them.

$ python3 string_template.py

TEMPLATE:
Variable : foo
Escape : $
Variable in text: fooiable

INTERPOLATION:
Variable : foo
Escape : %
Variable in text: fooiable

FORMAT:
Variable : foo
Escape : {}
Variable in text: fooiable

One key difference between templates and string interpolation or formatting is that the
type of the arguments is not taken into account. The values are converted to strings, and
the strings are inserted into the result. No formatting options are available. For example,
there is no way to control the number of digits used to represent a floating-point value.
A benefit, though, is that use of the safe_substitute() method makes it possible
to avoid exceptions if not all of the values needed by the template are provided as
arguments.

Listing 1.3: string_template_missing.py


import string

values = {'var': 'foo'}

t = string.Template("$var is here but $missing is not provided")

try:
print('substitute() :', t.substitute(values))
except KeyError as err:
print('ERROR:', str(err))

print('safe_substitute():', t.safe_substitute(values))
4 Chapter 1 Text

Since there is no value for missing in the values dictionary, a KeyError is raised by
substitute(). Instead of raising the error, safe_substitute() catches it and leaves the
variable expression alone in the text.

$ python3 string_template_missing.py

ERROR: 'missing'
safe_substitute(): foo is here but $missing is not provided

1.1.3 Advanced Templates


The default syntax for string.Template can be changed by adjusting the regular expression
patterns it uses to find the variable names in the template body. A simple way to do that
is to change the delimiter and idpattern class attributes.

Listing 1.4: string_template_advanced.py


import string

class MyTemplate(string.Template):
delimiter = '%'
idpattern = '[a-z]+_[a-z]+'

template_text = '''
Delimiter : %%
Replaced : %with_underscore
Ignored : %notunderscored
'''

d = {
'with_underscore': 'replaced',
'notunderscored': 'not replaced',
}

t = MyTemplate(template_text)
print('Modified ID pattern:')
print(t.safe_substitute(d))

In this example, the substitution rules are changed so that the delimiter is % instead of
$ and variable names must include an underscore somewhere in the middle. The pattern
%notunderscored is not replaced by anything, because it does not include an underscore
character.

$ python3 string_template_advanced.py

Modified ID pattern:
1.1 string: Text Constants and Templates 5

Delimiter : %
Replaced : replaced
Ignored : %notunderscored

For even more complex changes, it is possible to override the pattern attribute and define
an entirely new regular expression. The pattern provided must contain four named groups
for capturing the escaped delimiter, the named variable, a braced version of the variable
name, and invalid delimiter patterns.

Listing 1.5: string_template_defaultpattern.py


import string

t = string.Template('$var')
print(t.pattern.pattern)

The value of t.pattern is a compiled regular expression, but the original string is available
via its pattern attribute.

\$(?:
(?P<escaped>\$) | # Two delimiters
(?P<named>[_a-z][_a-z0-9]*) | # Identifier
{(?P<braced>[_a-z][_a-z0-9]*)} | # Braced identifier
(?P<invalid>) # Ill-formed delimiter exprs
)

This example defines a new pattern to create a new type of template, using {{var}} as the
variable syntax.

Listing 1.6: string_template_newsyntax.py


import re
import string

class MyTemplate(string.Template):
delimiter = '{{'
pattern = r'''
\{\{(?:
(?P<escaped>\{\{)|
(?P<named>[_a-z][_a-z0-9]*)\}\}|
(?P<braced>[_a-z][_a-z0-9]*)\}\}|
(?P<invalid>)
)
'''

t = MyTemplate('''
{{{{
6 Chapter 1 Text

{{var}}
''')

print('MATCHES:', t.pattern.findall(t.template))
print('SUBSTITUTED:', t.safe_substitute(var='replacement'))

Both the named and braced patterns must be provided separately, even though they are
the same. Running the sample program generates the following output:

$ python3 string_template_newsyntax.py

MATCHES: [('{{', '', '', ''), ('', 'var', '', '')]


SUBSTITUTED:
{{
replacement

1.1.4 Formatter
The Formatter class implements the same layout specification language as the format()
method of str. Its features include type coersion, alignment, attribute and field references,
named and positional template arguments, and type-specific formatting options. Most of the
time the format() method is a more convenient interface to these features, but Formatter
is provided as a way to build subclasses, for cases where variations are needed.

1.1.5 Constants
The string module includes a number of constants related to ASCII and numerical character
sets.

Listing 1.7: string_constants.py


import inspect
import string

def is_str(value):
return isinstance(value, str)

for name, value in inspect.getmembers(string, is_str):


if name.startswith('_'):
continue
print('%s=%r\n' % (name, value))

These constants are useful when working with ASCII data, but since it is increas-
ingly common to encounter non-ASCII text in some form of Unicode, their application is
limited.
1.2 textwrap: Formatting Text Paragraphs 7

$ python3 string_constants.py

ascii_letters='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW
XYZ'

ascii_lowercase='abcdefghijklmnopqrstuvwxyz'

ascii_uppercase='ABCDEFGHIJKLMNOPQRSTUVWXYZ'

digits='0123456789'

hexdigits='0123456789abcdefABCDEF'

octdigits='01234567'

printable='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQ
RSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'

punctuation='!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

whitespace=' \t\n\r\x0b\x0c'

TIP
Related Reading

• Standard library documentation for string.2


• String Methods3 : Methods of str objects that replace the deprecated functions in string.
• PEP 2924 : Simpler String Substitutions.
• Format String Syntax5 : The formal definition of the layout specification language used by For-
matter and str.format().

1.2 textwrap: Formatting Text Paragraphs


The textwrap module can be used to format text for output in situations where pretty-
printing is desired. It offers programmatic functionality similar to the paragraph wrapping
or filling features found in many text editors and word processors.

2 https://docs.python.org/3.5/library/string.html
3 https://docs.python.org/3/library/stdtypes.html#string-methods
4 www.python.org/dev/peps/pep-0292
5 https://docs.python.org/3.5/library/string.html#format-string-syntax
8 Chapter 1 Text

1.2.1 Example Data


The examples in this section use the module textwrap_example.py, which contains a string
sample_text.

Listing 1.8: textwrap_example.py


sample_text = '''
The textwrap module can be used to format text for output in
situations where pretty-printing is desired. It offers
programmatic functionality similar to the paragraph wrapping
or filling features found in many text editors.
'''

1.2.2 Filling Paragraphs


The fill() function takes text as input and produces formatted text as output.

Listing 1.9: textwrap_fill.py


import textwrap
from textwrap_example import sample_text

print(textwrap.fill(sample_text, width=50))

The results are something less than desirable. The text is now left justified, but the first
line retains its indent and the spaces from the front of each subsequent line are embedded
in the paragraph.

$ python3 textwrap_fill.py

The textwrap module can be used to format


text for output in situations where pretty-
printing is desired. It offers programmatic
functionality similar to the paragraph wrapping
or filling features found in many text editors.

1.2.3 Removing Existing Indentation


The previous example has embedded tabs and extra spaces mixed into the middle of the
output, so it is not formatted very cleanly. Removing the common whitespace prefix from
all of the lines in the sample text with dedent() produces better results and allows the use
of docstrings or embedded multiline strings straight from Python code while removing the
formatting of the code itself. The sample string has an artificial indent level introduced for
illustrating this feature.
1.2 textwrap: Formatting Text Paragraphs 9

Listing 1.10: textwrap_dedent.py


import textwrap
from textwrap_example import sample_text

dedented_text = textwrap.dedent(sample_text)
print('Dedented:')
print(dedented_text)

The results are starting to look better.

$ python3 textwrap_dedent.py

Dedented:

The textwrap module can be used to format text for output in


situations where pretty-printing is desired. It offers
programmatic functionality similar to the paragraph wrapping
or filling features found in many text editors.

Since “dedent” is the opposite of “indent,” the result is a block of text with the common
initial whitespace from each line removed. If one line is already indented more than another,
some of the whitespace will not be removed.
Input like

Line one.
Line two.
Line three.

becomes

Line one.
Line two.
Line three.

1.2.4 Combining Dedent and Fill


Next, the dedented text can be passed through fill() with a few different width values.

Listing 1.11: textwrap_fill_width.py


import textwrap
from textwrap_example import sample_text

dedented_text = textwrap.dedent(sample_text).strip()
for width in [45, 60]:
print('{} Columns:\n'.format(width))
10 Chapter 1 Text

print(textwrap.fill(dedented_text, width=width))
print()

This produces outputs in the specified widths.

$ python3 textwrap_fill_width.py

45 Columns:

The textwrap module can be used to format


text for output in situations where pretty-
printing is desired. It offers programmatic
functionality similar to the paragraph
wrapping or filling features found in many
text editors.

60 Columns:

The textwrap module can be used to format text for output in


situations where pretty-printing is desired. It offers
programmatic functionality similar to the paragraph wrapping
or filling features found in many text editors.

1.2.5 Indenting Blocks


Use the indent() function to add consistent prefix text to all of the lines in a string. This
example formats the same example text as though it was part of an email message being
quoted in the reply, using > as the prefix for each line.

Listing 1.12: textwrap_indent.py


import textwrap
from textwrap_example import sample_text

dedented_text = textwrap.dedent(sample_text)
wrapped = textwrap.fill(dedented_text, width=50)
wrapped += '\n\nSecond paragraph after a blank line.'
final = textwrap.indent(wrapped, '> ')

print('Quoted block:\n')
print(final)

The block of text is split on newlines, the prefix is added to each line that contains text,
and then the lines are combined back into a new string and returned.

$ python3 textwrap_indent.py

Quoted block:
1.2 textwrap: Formatting Text Paragraphs 11

> The textwrap module can be used to format text


> for output in situations where pretty-printing is
> desired. It offers programmatic functionality
> similar to the paragraph wrapping or filling
> features found in many text editors.

> Second paragraph after a blank line.

To control which lines receive the new prefix, pass a callable as the predicate argument to
indent(). The callable will be invoked for each line of text in turn and the prefix will be
added for lines where the return value is true.

Listing 1.13: textwrap_indent_predicate.py


import textwrap
from textwrap_example import sample_text

def should_indent(line):
print('Indent {!r}?'.format(line))
return len(line.strip()) % 2 == 0

dedented_text = textwrap.dedent(sample_text)
wrapped = textwrap.fill(dedented_text, width=50)
final = textwrap.indent(wrapped, 'EVEN ',
predicate=should_indent)

print('\nQuoted block:\n')
print(final)

This example adds the prefix EVEN to lines that contain an even number of characters.

$ python3 textwrap_indent_predicate.py

Indent ' The textwrap module can be used to format text\n'?


Indent 'for output in situations where pretty-printing is\n'?
Indent 'desired. It offers programmatic functionality\n'?
Indent 'similar to the paragraph wrapping or filling\n'?
Indent 'features found in many text editors.'?

Quoted block:

EVEN The textwrap module can be used to format text


for output in situations where pretty-printing is
EVEN desired. It offers programmatic functionality
EVEN similar to the paragraph wrapping or filling
EVEN features found in many text editors.
12 Chapter 1 Text

1.2.6 Hanging Indents


In the same way that it is possible to set the width of the output, the indent of the first
line can be controlled independently of subsequent lines.

Listing 1.14: textwrap_hanging_indent.py


import textwrap
from textwrap_example import sample_text

dedented_text = textwrap.dedent(sample_text).strip()
print(textwrap.fill(dedented_text,
initial_indent='',
subsequent_indent=' ' * 4,
width=50,
))

This ability makes it possible to produce a hanging indent, where the first line is indented
less than the other lines.

$ python3 textwrap_hanging_indent.py

The textwrap module can be used to format text for


output in situations where pretty-printing is
desired. It offers programmatic functionality
similar to the paragraph wrapping or filling
features found in many text editors.

The indent values can include non-whitespace characters, too. The hanging indent can be
prefixed with * to produce bullet points, for example.

1.2.7 Truncating Long Text


To truncate text to create a summary or preview, use shorten(). All existing whitespace,
such as tabs, newlines, and series of multiple spaces, will be standardized to a single space.
Then the text will be truncated to a length less than or equal to what is requested, between
word boundaries so that no partial words are included.

Listing 1.15: textwrap_shorten.py


import textwrap
from textwrap_example import sample_text

dedented_text = textwrap.dedent(sample_text)
original = textwrap.fill(dedented_text, width=50)

print('Original:\n')
print(original)
Other documents randomly have
different content
footman in his brown livery assisted her into the carriage.
Then she smiled merrily, and bowed as I raised my hat, and
she was borne away westward in the stream of fine
equipages, hers the smartest of them all.

A week later, having seen nothing further of her, I wrote


and received a prompt response. Then in the happy autumn
days that followed we contrived to meet often, and on each
occasion I grew deeper and deeper in love with her. Since
that evening when we had stood together beneath the
street lamp in Kensington, she had made no mention of the
pencil-case or of its owner. Indeed, it seemed that her
sudden identification of it had betrayed her into
acknowledging that its owner had been her lover, and that
now she was trying to do all she could to remove any
suspicion from my mind.

Nevertheless, the remembrance of that crime and of all the


events of that midnight adventure was ever within my
mind, and I had long ago determined to make its
elucidation the chief object of my life. I had placed myself
beneath the thrall of some person unknown, and meant to
extricate myself and become again a free agent at all costs.

On several occasions I had seen the cabman West on the


rank at Hyde Park Corner, but although he had constantly
kept his eyes open in search of Edna, his efforts had all
been in vain. I had seen also the old cab-driver who bore
the nickname “Doughy,” but it turned out that it had not
been his cab which my mysterious protectress had taken
after parting from me. One point, however, I settled
satisfactorily. On one of our walks together I contrived that,
the man West should see Mabel, but he afterwards declared
that the woman of whom he was in search did not in the
least resemble her. Therefore, it was certain that Mabel and
Edna were not, as I had once vaguely suspected, one and
the same person.

Sometimes I would meet my idol after her studies at the


Royal Academy of Music, and accompany her across the
park; at others we would stroll together in the unfrequented
part of Kensington Gardens, or I would walk with her
shopping and carry her parcels, all our meetings being, of
course, clandestine ones.

One morning in the middle of November I was overfed at


receiving an invitation from Mrs Anson to dine at The
Boltons, and a couple of days later the sum of my happiness
was rendered complete by finding myself seated beside
Mabel in her own home.

The house possessed an air of magnificence and luxury


which I scarcely expected. It was furnished with great
elegance and taste, while the servants were of an even
more superior character than the house itself. Among the
homes of my many friends in the West End this was
certainly the most luxurious, for money seemed to have
been literally squandered upon its appointments, and yet
withal there was nothing whatever garish nor any trace of a
plebeian taste. There was a combined richness and
quietness about the whole place which impressed one with
an air of severity, while the footman who ushered me in was
tall, almost a giant in stature, and solemn as a funeral
mute.

Mrs Anson rose and greeted me pleasantly, while Mabel, in


a pretty gown of coral-pink, also shook my hand and raised
her fine dark eyes to mine with a glance of pleasure and
triumph. It was, no doubt, due to her that I had been
bidden there as guest. A red-headed, ugly-faced man
named Hickman, and a thin, angular, irritating woman,
introduced to me as Miss Wells, were my only fellow-guests.
The man regarded me with some suspicion as I entered,
and from the first I took a violent dislike to him. It may
have been his forbidding personal appearance which caused
my distrust. Now that I reflect, I think it was. His face was
bloated and deeply furrowed, his eyes large, his lips thick
and flabby, his reddish beard was ill-trimmed and scanty.
He was thick-necked; his face was further disfigured by a
curious dark-blue scar upon the left jaw, and I could not
help remarking within myself, that if some faces resembled
those of animals, his was closely allied to that of a savage
bulldog. Indeed, I had never before seen such an eminently
ugly face as his.

Yet he spoke with the air and perfect manner of a


gentleman. He bowed with refined dignity as I was
introduced, although I thought his smile seemed
supercilious, while I was almost certain that he exchanged a
curious, contemptuous look with Mabel, who stood behind
me.

Was he aware of our little exchanges of confidences? Had


he secretly watched us in our walks along the leafy byways
of Kensington Gardens, and detected that I loved her? It
seemed very much as though he had, and that he had
endeavoured to disparage me in her eyes.

At Mrs Anson’s invitation, I took Mabel in to dinner, and sat


next her, while opposite us sat the dog-faced man with the
irritating spinster. The latter was a fitting companion for
him, bony of countenance, her back straight as a board, her
age uncertain, and her voice loud, high-pitched, and
rasping. She wore a number of bangles on her left wrist;
one of them had pigs and elephants hanging on it, with
hearts, crosses, bells, and framed and glazed shamrock
leaves mixed in. That would not have mattered much had
she not been eating, but as dinner progressed the room
grew a trifle warm, and she unfortunately had a fan as well
as those distressing bangles, which fan she rhythmically
waved to and fro, playing the orchestra softly when fanning
herself, or loudly as she plied her knife and fork “click-clack,
jingle-jingle, tinkle-tinkle, click-clack!” until the eternal
music of those pigs, elephants, crosses, hearts and bells
prevented anything beyond a jerky conversation. She
turned and twisted and toyed with her menu, tinkling and
jingling the whole time like a coral consoler or an infant’s
rattle. Little wonder, I thought, that she remained a
spinster. With such an irritating person to head his
household, the unfortunate husband would be a candidate
for Colney Hatch within a month. Yet she was evidently a
very welcome guest at Mrs Anson’s table, for my hostess
addressed her as “dear,” and seemed to consider whatever
positive opinion she expressed as entirely beyond dispute.

I liked Mrs Anson. Although of that extremely frigid type of


mother, very formal and unbending, observing all the rules
of society to the letter, and practically making her life a
burden by the conventionalities, she possessed,
nevertheless, a warm-hearted affection for her child, and
seemed constantly solicitous of her welfare. She spoke with
the very faintest accent with her “r’s,” and I had, on the
first evening we had met at the colonel’s, wondered
whether she were of Scotch, or perhaps foreign, extraction.
The general conversation in the interval of the Irritating
Woman’s orchestra turned upon foreign travel, and
incidentally, in answer to an ingenious question I put to her,
she told me that her father had been German, but that she
had nearly all her life lived in England.

The Irritating Woman spoke of going to the Riviera in


December, whereupon Mabel remarked—
“I hope mother will go too. I’m trying to persuade her.
London is so dull and miserable in winter compared with
Cannes or Nice.”

“You know the Riviera well, I suppose?” I inquired of her.

“Oh, very well,” she responded. “Mother and I have spent


four winters in the south. There’s no place in Europe in
winter like the Côte d’Azur—as the French call it.”

“I much prefer the Italian Riviera,” chimed Miss Wells’s


high-pitched voice. She made it a point of honour to differ
with everybody. “At Bordighera, Ospedaletti, San Remo, and
Alassio you have much better air, the same warmth, and at
about half the price. The hotels in Nice and Cannes are
simply ruinous.” Then, turning to Mrs Anson, she added,
“You know, dear, what you said last year.”

“We go to the Grand, at Nice, always,” answered Mrs Anson.


“It is dear, certainly, but not exaggeratedly so in comparison
with the other large hotels.”

“There seems of late to have been a gradual rise in prices


all along the Riviera,” remarked Hickman. “I’ve experienced
it personally. Ten or twelve years ago lived in Nice for the
season for about half what it costs me now.”

“That exactly bears out my argument,” exclaimed the


Irritating Woman, in triumph. “The fact is that the French
Riviera has become far too dear, and English people are,
fortunately for themselves, beginning to see that by
continuing their journey an extra twenty miles beyond Nice
they can obtain just as good accommodation, live better,
breathe purer air, and not be eternally worried by those
gaudy tinsel-shows called Carnivals, or insane attempts at
hilarity miscalled Battles of Flowers.”
“Oh, come, Miss Wells,” protested Mabel, “surely you won’t
condemn the Battles of Flowers at Nice! Why, they’re
acknowledged to be amongst the most picturesque
spectacles in the world!”

“I consider, my dear, that they are mere rubbishy ruses on


the part of the Niçois to cause people to buy their flowers
and throw them into the roadway. It’s only a trick to
improve their trade.”

We all laughed.

“And the Carnival?” inquired Hickman, much amused.

“Carnival!” she snorted. “A disgraceful exhibition of a town’s


lawlessness. A miserable pageant got up merely to attract
the unsuspecting foreigner into the web spread for him by
extortionate hotel-keepers. All the so-called fun is
performed by paid mountebanks; the cars are not only
inartistic, but there is always something extremely offensive
in their character, while the orgies which take place at the
masked balls at the Casino are absolutely disgraceful. The
whole thing is artificial, and deserves no support at all from
winter visitors.”

Mrs Anson, for once, did not agree with this sweeping
condemnation, while Mabel declared that she always
enjoyed the fun of the battles of flowers and paper confetti,
although she admitted that she had never had the courage
to go out on those days when the pellets of lime, or “harp
confetti,” are permitted. Both Hickman and myself
supported Mabel in defence of the annual fêtes at Nice as
being unique in all the world.

But the Irritating Woman was not to be convinced that her


opinions were either ill-formed or in the least distorted. She
had never been present at a Carnival ball, she admitted, but
it had been described to her by two estimable ladies who
had, and that was, for her, sufficient. They were a pair of
pious souls, and would, of course, never exaggerate to the
length of a lie.

Dinner over, the ladies retired, and Hickman and myself


were left to smoke and gossip. He was certainly a very ugly
man, and at times asserted an overbearing superiority in
conversation; but having watched him very closely, I at
length arrived at the conclusion that this was his natural
manner, and was not intended to be offensive. Indeed, ever
since that first moment when I had entered and been
introduced, he had shown himself to be very pleasant and
affable towards me.

“Poor Miss Wells!” he laughed, after the door had closed.


“She’s so infernally positive about everything. It would be
as good as an entertainment to induce her to expound her
views upon religious matters.”

“Any argument seems utterly useless,” I remarked.

“Do you know Nice well?” he inquired, after reflecting a


moment.

“I’ve spent three winters there,” I answered.

“And at Monte Carlo, I suppose?”

“Yes, of course,” I responded, laughing. “I suppose scarcely


any man goes to Nice without going over to Monty and
risking a few louis.”

“Were you lucky?”

“So, so. One season I won five thousand francs. In fact, I’ve
never lost on the whole season. I’ve always left the Riviera
with some of the bank’s money.”

“Then you can heartily congratulate yourself,” he said, “I’m


the reverse. I generally lose. Do you believe in any system
at roulette?”

“No; they are all frauds,” I answered promptly. “Except


one,” he interposed. “There’s one based on the law of
averages, which must turn up in your favour if you’re only
patient enough. The reason why it is so difficult is because
it’s such a long and tedious affair.”

“Explain it,” I urged, for a new system that was infallible


was, to me, of greatest interest. I had, in the days before
my blindness, made a study of the chances at roulette, and
had played carefully upon principles which had, to me,
appeared most natural. The result had been that with care I
had won—not much, it was true—but it was better than
leaving one’s money to swell the company’s dividends.

“The system,” he said, tossing off his glass of curaçoa at


one gulp, “is not at all a complicated one. If you study the
permanences of any table—you can get them from the
Gazette Rose—you’ll find that each day the largest number
of times either colour comes up in succession is nine. Now,
all you have to do is to go to a table at the opening of the
play, and taking one colour, red or black it makes no
difference, stake upon it, and allow your money to
accumulate until it is swept away. If the colour you stake
upon comes up eight times in succession, and you have
originally staked twenty francs, your gains lying on the table
will amount to two thousand five hundred and sixty francs.
Even then, don’t touch it. The colour must, in the law of
averages, come up nine times in succession each day,
taking the week through. If it comes up, you’ll win five
thousand and twenty francs for the louis you staked, and
then at once leave the table, for it will not come up nine
times again that day. Of course, this may occur almost at
the opening of the play, or not until the table is near
closing, therefore it requires great patience and constant
attendance. To-day it may not come up nine times, but it
will probably come up nine times on two occasions to-
morrow, and so the average always rights itself.”

His theory was certainly a novel one, and impressed me.


There might, I thought, be something in it. He had never
had patience to try it, he admitted, but he had gone
through a whole year’s “permanences,” and found that only
on three or four occasions had it failed.

For half an hour or so he sat lucidly explaining the results of


his studies of the game with the air of a practised gambler.
In these I became at once interested—as every man is who
believes he has found the secret of how to get the right side
of the bank; but we were at length compelled to put down
our cigars, and he led the way into the drawing-room,
where the ladies awaited us.

The room was a large, handsome one, elegantly furnished,


and lit by two great lamps, which shed a soft, subdued light
from beneath their huge shades of silk and lace. Mabel was
sitting at the open grand piano, the shaded candlelight
causing the beautiful diamond star in the coils of her dark-
brown hair to flash with a dazzling iridescence, and as I
entered she turned and gave me a sweet smile of welcome.

A second time I glanced around that spacious apartment,


then next instant stood breathless—transfixed.

I could not believe my own eyes. It seemed absolutely


incredible. Yet the truth was beyond all doubt.
In the disposition of the furniture, and in the general
appointments of that handsome salon, the home of the
woman I so dearly loved, I recognised the very room which
I had once explored with my keen sense of touch—the room
in which had been committed that ghastly, mysterious,
midnight crime!
Chapter Fifteen.
What I Saw.

“How you men gossip!” Mabel exclaimed, tingling upon the


piano-stool, and laughing merrily.

“I wasn’t aware that we had been very long,” I answered,


sinking into a low armchair near her. “If so, I’m sure I
apologise. The fact is, that Mr Hickman was explaining a
new system of how to break the bank at Monte Carlo.”

“Oh, Mr Hickman!” she cried, turning at once to him. “Do


explain it, and I’ll try it when we go to the Riviera.”

“Mabel, my dear,” exclaimed her mother, scandalised, “you’ll


do nothing of the kind. You know I don’t approve of
gambling.”

“Oh, I think it’s awfully good fun,” her daughter declared.

“If you win,” I added.

“Of course,” she added; then, turning again to Hickman, she


induced him to explain his new and infallible system just as
he had explained it to me.

The trend of the conversation was, however, lost to me. My


ears were closed to all sound, and now that I reflect I am
surprised that I succeeded in retaining my self-possession. I
know I sat there rigid, as one held motionless in terror; I
only replied in monosyllables to any remark addressed to
me, and I knew instinctively that the colour had left my
countenance. The discovery was as bewildering as it was
unexpected.
Every detail of that handsome room was exactly as I had
pictured it. The blind, with their keen sense of touch, are
quick to form mental impressions of places and things, and
the general character of this apartment I had riveted upon
my mind with the fidelity of a photograph.

The furniture was of gilt, just as I had detected from its


smoothness, and covered with a rich brocade in wide stripes
of art green and dull red-brown—an extremely handsome
pattern; the carpet was dark, with a pile so thick that one’s
feet fell noiselessly; the three long windows, covered by
heavy curtains of brocade to match the furniture, reached
from the high-painted ceiling to the ground, exactly as I
had found them in my blind gropings. About the room were
two or three tables with glass tops, in trays beneath which
were collections of choice bric-à-brac, including some
wonderful Chinese carvings in ivory, while before the
fireplace was spread the great tiger-skin, with paws and
head preserved, which I so well remembered.

I sat there speechless, breathless. Not a single detail was


there wanting. Never before, in all my life, had amazement
held me so absolutely dumbfounded.

Close to where I saw was a spacious couch, over the centre


of which was thrown an antimacassar of silken crochet-
work. It was covered with the same brocade as the rest of
the furniture, and I stretched forth my hand, with feigned
carelessness and touched it. Its contact was the same, its
shape exact; its position in the room identical.

Upon that very couch I had reclined while the foul tragedy
had been enacted in that room. My head swam; I closed my
eyes. The great gilt clock, with its pendulum representing
the figure of a girl swinging beneath the trees, standing on
the mantelshelf, ticked out low and musically, just as it had
done on that fateful night. In an instant, as I sat with head
turned from my companions and my eyes shut, the whole of
that tragic scene was re-enacted. I heard the crash, the
woman’s scream, the awe-stricken exclamation that
followed in the inner room. I heard, too, the low swish of a
woman’s skirts, the heavy blow struck by an assassin’s
hand, and in horror felt the warm life-blood of the unknown
victim as it trickled upon my hand.

Mabel suddenly ran her white fingers over the keys, and the
music brought me back to a realisation of my true position.
I had at length discovered the actual house in which the
mysterious tragedy had been enacted, and it became
impressed upon me that by the exercise of greatest care I
might further be enabled to prosecute secret investigations
to a successful issue, and at length solve the enigma.

My eyes fixed themselves upon the couch. It was the very


spot where I had rested, sightless, helpless, while those
strange events had taken place about me. Was it any
wonder that I became filled with apprehensions, or that I
sat there petrified as one turned to stone?

The square, dark-green antimacassar had been placed in


the exact centre of the couch, and sewed down in order to
keep it in its place. Where I was sitting was fortunately in
the shadow, and when Mabel commenced playing I rose—
unsteadily I think—and reseated myself upon the couch, as
being more comfortable. Then, while the woman who held
me entranced played a selection from the “Trovatore,” I,
unnoticed by the others, succeeded in breaking the stitches
which tacked the antimacassar to the brocade. The feat was
a difficult one, for one does not care to be detected tearing
the furniture of one’s hostess. Nevertheless, after ten
minutes or so I succeeded in loosening it, and then, as if by
the natural movement of my body, commenced to work
aside.

The music ceased, and even though all my attention was


now centred upon my investigations, I congratulated Mabel
upon her accurate execution. Hickman was standing beside
her, and together they began to search for some piece he
had requested her to play, while Miss Wells, with her hearts
and elephants jingling, turned to me and commenced to
talk. By this I was, of course, interrupted; nevertheless,
some ten minutes later, I rose, and naturally turned back to
straighten the rumpled antimacassar. In doing so I
managed to lift it and glance beneath.

In an instant the truth was plain. Concealed beneath that


square of green crochet-work was a large dark-brown stain
upon the brocade. It was the mark of the life-blood of that
thin, well-dressed, unknown victim, who had, in an instant,
been struck to the heart!

The shock at its discovery caused me to start, but next


instant I smoothed out the antimacassar into its former
place without attracting any attention, and passed across
the room with the motive of inspecting an object which I
well remembered discovering when I had made my blind
search. Upon a pedestal of black marble stood an exquisite
little statuette of a Neapolitan dancing-woman, undoubtedly
the work of some Italian master. Without pausing to
examine it, I took in its every detail as I passed. It was
exactly as I had felt it, and in the self-same spot as on that
fatal night.

Beside the couch, as I turned again to look, I saw that a


large skin rug had been thrown down. Without doubt it had
been placed there to conceal the ugly stain of blood upon
the carpet.
And yet there, on the scene of one of the foulest and most
cowardly assassinations, we were actually spending the
evening quietly, as became a respectable household. The
thing seemed absolutely incredible. A dozen times I
endeavoured to persuade myself that the whole discovery
was but a chimera, arising from my disordered imagination.
Nevertheless, it was impossible to disguise from myself the
fact that in every detail the truth was borne out. In that
very room the unknown man had been struck dead. The
marks of his blood still remained as evidence of the truth.

I saw that beside the high lamps at that moment in use,


there was a magnificent candelabra suspended from the
ceiling, and in this were electric lamps. Then, at the door, I
noticed the switch, and knew that it was the same which I
had heard turned off by the assassin before leaving the
house.

At the end of the room, too, were the folding doors, now
concealed by curtains. It was through those very doors that
Edna, my mysterious protectress, had passed and repassed
to that inner room whence had come the sound of
champagne being uncorked and the woman’s piercing
scream.

Mabel leaned over and spoke to me, whereupon I sank


again into the chair I had previously occupied. She began to
chat, but although her beautiful eyes held me fixed, and her
face seemed more handsome than any I had ever seen, the
diamonds in her hair dazzled my eyes, and I fear that my
responses were scarcely intelligible.

“You are not quite yourself to-night, I think,” she remarked


at last, rising from the piano, and taking the low chair that I
drew up for her. “Are you unwell?”
“Why?” I asked, laughing.

“Because you look rather pale. What’s the matter?”

“Nothing,” I answered, as carelessly as I could. “A slight


headache. But it has passed now.”

My eyes wandered to those curtains of green plush. How I


longed to enter that room beyond!

At that moment she took out her handkerchief. Even that


action added to the completion of the mental picture I had
formed. Her tiny square of lawn and lace exhaled a sweet
odour. It was that of peau d’Espagne, the same subtle
perfume used by the mysterious Edna! It filled my nostrils
until I seemed intoxicated by its fragrance combined with
her beauty.

Her dress was discreetly decolleté, and as she sat chatting


to me with that bright vivaciousness which was so
charming, her white neck slowly heaved and fell. She had, it
seemed, been striving all the evening to get a tête-à-tête
chat with me, but the chatter of that dreadful Irritating
Woman and the requests made by Hickman had prevented
her.

As she gossiped with me, now and then waving her big
feather fan, she conveyed to my mind an impression of
extreme simplicity in the midst of the most wonderful
complexity. She seemed to take the peculiar traits from
many characters, and so mingle them that, like the
combination of hues in a sunbeam, the effect was as one to
the eye. I had studied her carefully each time we had met,
and had found that she had something of the romantic
enthusiasm of a Juliet, of the truth and constancy of a
Helen, of the dignified purity of an Isabel, of the tender
sweetness of a Viola, of the self-possession and intellect of
a Portia—combined together so equally and so
harmoniously that I could scarcely say that one quality
predominated over the other. Her dignity was imposing, and
stood rather upon the defensive; her submission, though
unbounded, was not passive, and thus she stood wholly
distinct in her sweetness from any woman I had ever met.

The following day was one on which she was due to take
her music-lesson, and I inquired whether I might, as usual,
meet her and escort her across the Park.

“You are really very kind,” she responded; “but I fear I take
up far too much of your time.”

“Not at all,” I hastened to assure her. “I always enjoy our


walks together.”

She smiled, but a moment later said—

“I fear that I shall be prevented from going to Hanover


Square to-morrow, as I shall be making calls with mother.
We’ve been neglecting to call of late, and have such a host
to make.”

“Then I shan’t see you at all to-morrow?” I said in deep


disappointment.

“No, I fear not,” she answered. “As a matter of fact, my


movements for the next few days are rather uncertain.”

“But you’ll write and tell me when you are free?” I urged
earnestly.

“If you wish,” she responded, smiling sweetly. Apparently


she was in no wise averse to my companionship, a fact
which had become to me more apparent now that she had
induced her mother to invite me to their table.
I endeavoured to extract from her some appointment, but
she only whispered—

“Remember that our meetings are clandestine. Don’t let


them overhear us. Let’s change the subject.” And then she
began to discuss several of the latest novels.

She had apparently a wide knowledge of French fiction, for


she explained how a friend of hers, an old schoolfellow, who
had married a French baron and lived in Paris, sent her
regularly all the notable novels. Of English fiction, too, she
was evidently a constant reader, for she told me much
about recent novels that I was unaware of, and criticised
style in a manner which betrayed a deep knowledge of her
subject.

“One would almost think you were a lady novelist, or a


book-reviewer,” I remarked, in response to a sweeping
condemnation which she made regarding the style of a
much-belauded writer.

“Well, personally, I like books with some grit in them,” she


declared. “I can’t stand either the so-called problem novel,
or a story interlarded with dialect. If any one wants nasty
problems, let them spend a few shillings in the works of
certain French writers, who turn out books on the most
unwholesome themes they can imagine, and fondly believe
themselves realists. We don’t want these queue-de-siècle
works in England. Let us stick to the old-fashioned story of
love, adventure, or romance. English writers are now
beginning to see the mistake they once made in trying to
follow the French style, and are turning to the real
legitimate novel of action—the one that interests and grips
from the first page to the last.”
She spoke sensibly, and I expressed my entire accord with
her opinion. But this discussion was only in order to hide
our exchange of confidences uttered in an undertone while
Hickman and the two ladies were chatting at the further end
of the room.

All the time I was longing to get a sight of the interior of the
adjoining apartment, the room whence had burst forth that
woman’s agonised cry in the stillness of the night. I racked
my brain to find some means of entering there, but could
devise none. A guest can hardly wander over his hostess’s
house on the first occasion he receives an invitation.
Besides, to betray any interest in the house might, I
reflected, arouse some suspicion. To be successful in these
inquiries would necessitate the most extreme caution.

The fragrant odour of peau d’Espagne exhaled by her


chiffons seemed to hold me powerless.

The gilt clock with its swinging girl had already struck
eleven on its silver bell, and been re-echoed by another
clock in the hall playing the Westminster chimes, when
suddenly Mrs Anson, with a book in her hand, looked across
to her daughter, saying—

“Mabel, dear, I’ve left my glasses on the table in the library.


Will you kindly fetch them for me?”

In an instant I saw my chance, and, jumping to my feet,


offered to obtain them. At first she objected, but finding me
determined, said—

“The library is the next room, there. You’ll find them on the
writing-table. Mother always leaves them there. It’s really
too bad to thus make a servant of you. I’ll ring for Arnold.”
“No, no,” I protested, and at once went eagerly in search of
them.
Chapter Sixteen.
The Inner Room.

The adjoining room was, I found, in the front part of the


house—a rather small one, lined on one side with books,
but furnished more as a boudoir than a library, for there
were several easy-chairs, a work-table, and a piano in a
corner. At this instrument the mysterious player had on that
night sat executing Chopin’s “Andante-Spinato” the moment
before it became interrupted by some tragic and
unexpected spectacle. I glanced around and noted that the
furniture and carpet were worn and faded, that the books
were dusty and evidently unused, and that the whole place
presented an air of neglect, and had nothing whatever in
keeping with the gorgeousness of the other handsome
apartments.

The glasses were, as Mrs Anson had said, lying beside the
blotting-pad upon a small rosewood writing-table. I took
them up, and, having made a tour of inspection, was about
to leave the place, when suddenly, on the top of some
books upon a shelf close to the door, I espied a small
volume.

The curious incident of the birthday book occurred to me;


therefore I took down the little volume and found that it
really was a birthday book. No name was inscribed on the
title-page as owner, but there were many names scribbled
therein. In swift eagerness I turned to the page of my own
birthday—the 2nd of July. It was blank.

I stood pondering with the book still in my hand. The


absence of my name there proved one or two things, either
I had not signed a birthday book at all, or, if I had, it was
not the one I had discovered. Now, there are frequently two
birthday-books in one house, therefore I resolved, ere I
gave the matter reflection, to prosecute my investigations
further and ascertain whether there was not a second book.

With this object I made a second tour around the room,


noting the position of every article of furniture. Some music
lay scattered beside the piano, and, on turning it over, I
found the actual copy of Chopin’s “Andante” which had been
played on the night of the tragedy. The cover had been half
torn away, but, on examining it closely beneath the light, I
detected plainly a small smear of blood upon it.

Truly the house was one of mystery. In that room several


persons had drunk champagne on that memorable night
when blind Fate led me thither; in that room a woman had,
according to the man’s shout of alarm, been foully done to
death, although of this latter fact I was not altogether sure.
At any rate, however, it was plain that some tragic event
had previously taken place there, as well as in that room
beyond where I had reclined blind and helpless. It was
strange also that the apartment should remain neglected
and undusted, as though the occupants entertained some
dislike to it. But I had been absent long enough, and,
returning to the drawing-room with the missing glasses,
handed them to Mrs Anson.

Hickman had, in my absence, crossed to Mabel, and was


sitting beside her in earnest conversation, therefore I was
compelled to seat myself with my hostess and the Irritating
Woman and chat with them. But ere long I contrived again
to reach the side of the woman whom I adored, and to
again press her for an appointment.
“It is far better forme to write to you,” she answered,
beneath her breath. “As I’ve told you, we have so many
calls to make and cards to leave.”

“Your mother tells me that you have a box for the Prince of
Wales’s on Saturday night, and has asked me to join you,” I
said. Her eyes brightened, and I saw that she was delighted
at the prospect. But she expressed a hope that I wouldn’t
be bored.

“Bored!” I echoed. “Why, I’m never bored when in your


company. I fear that it’s the other way about—that I bore
you.”

“Certainly not,” she responded decisively. “I very soon


contrive to give persons who are bores their congé. Mother
accuses me of rudeness to them sometimes, but I assure
you I really can’t help being positively insulting. Has mother
asked you to dine on Saturday?”

“Yes,” I answered. “But shan’t I see you before then?”

“No; I think it is very unlikely. We’ll have a jolly evening on


Saturday.”

“But I enjoy immensely those walks across the Park,” I


blurted forth in desperation.

“And I also,” she admitted with a sweet frankness. “But this


week it is utterly impossible to make any arrangements.”

Mention of the theatre afforded me an opportunity of


putting to her a question upon which, during the past
couple of hours, I had reflected deeply.

“You’ve, of course, been to the Exhibition at Earl’s Court,


living here in the immediate vicinity,” I said.
“I’ve only been once,” she answered. “Although we’ve had
this house nearly two years, exhibitions don’t appeal to me
very much. I was there at night, and the gardens were
prettily illuminated, I thought.”

“Yes,” I said. “With the exception of the gardens, there is far


too much pasteboard scenic effect. I suppose you noticed
that serrated line of mountains over which the eternal
switchback runs? Those self-same mountains, repainted
blue, grey, or purple, with tips of snow, have, within my
personal knowledge, done duty as the Alps, the Pyrenees,
the Rockies, and the Atlas, not counting half a dozen other
notable ranges.”

She laughed, slowly fanning herself the while.

By her reply I had obtained from her own lips a most


important fact in the inquiry I intended now to prosecute,
namely, that this house had been her home for nearly two
years. Therefore it had been in Mrs Anson’s possession at
the time of the tragedy.

Since the moment when I had first recognised that; room


as the one in which I had been present on the night of the
mysterious assassination, the possibility had more than
once occurred to me that Mrs Anson might have;
unwittingly taken it ready furnished after the committal of
the crime. Such, however, was not the fact. Mabel had
asserted that for nearly two years she had lived, there.

Again, even as I sat there at her side, deep in admiration of


her magnificent figure in that striking toilette of coral-pink,
with its soft garniture of lace and chiffons, I could not help
reflecting upon the curious fact that she should have
recognised the dead man’s pencil-case. And she had, by her
silence, assented to my suggestion that he had been her
lover. That little gold pencil-case that I had found in his
pocket when he lay dead at that very spot where we were
now sitting had been one of her love-gifts to him.

The mystery hourly grew more puzzling and bewildering.


Yet so also each hour that I was at her side I fell deeper and
deeper in love with her, longing always for opportunity to
declare to her the secret of my heart, yet ever fearing to do
so lest she should turn from me.

Our unexpected meeting at Grosvenor Gate, after I had


received that letter from my anonymous correspondent,
combined with the startling discovery that it was actually in
her house that the mysterious tragedy had been enacted;
that in that very room the smart, refined young man who
had been her lover had fought so fiercely for life, and had
yet been struck down so unerringly, formed an enigma
inscrutable and perplexing.

The mystery, however, did not for one moment cause me to


waver in my affection for her. I had grown to love her fondly
and devotedly; to adore her as my idol, as the one who held
my whole future in her hands, therefore whatever suspicion
arose within my mind—and I admit that grave suspicion did
arise on many occasions—I cast it aside and fell down to
worship at the shrine of her incomparable beauty.

Miss Wells’s carriage was announced at last, and the


Irritating Woman, tinkling and jingling, rose with a wearied
sigh and took her leave, expressing her thanks for “a most
delightful evening, my dear.”

Mabel, mischievous as a school-girl, pulled a grimace when


the music of the bangles had faded in the hall outside, at
which we laughed in merry chorus.
With Hickman I remained ten minutes or so longer, then
rose, also declaring that it was time we left. The grave man-
servant Arnold served us with whiskies and sodas in the
dining-room, and, Mabel having helped me on with my
covert-coat, we shook hands with our hostess and her
daughter, and left in company.

The night was bright and starlit, and the air refreshing.
Turning to the left after leaving the house, we came
immediately to a road which gave entrance to that secluded
oval called The Boltons. I looked at the name-plate, and
saw it was named Gilston Road. It must have been at this
corner that I had been knocked down by a passing cab
when, on my first adventurous journey alone, I had
wandered so far westward.

I turned to look back, and noticed that from the dining-


room window of the house we had just left any occurrence
at the corner in question could be distinctly seen. Edna had
explained that she had witnessed my accident from that
window, and in this particular had apparently told me the
truth.

The remarkable and unexpected discoveries of that evening


had produced a veritable tumult of thoughts within my
brain, and as I walked with Hickman I took no note of his
merry, irresponsible gossip, until he remarked—

“You’re a bit preoccupied, I think. You’re pondering over


Mabel’s good looks, I suppose?”

“No,” I answered, starting at this remark. Then, to excuse


myself, I added, “I was thinking of other things. I really beg
your pardon.”

“I was asking your opinion of Mabel. Don’t you consider her


extremely handsome?”
“Of course,” I answered, trying to suppress my enthusiasm.
“She’s charming.”

“A splendid pianist, too.”

“Excellent.”

“It has always been a wonder to me that she has never


become engaged,” he remarked. “A girl with her personal
charms ought to make an excellent match.”

“Has she never been engaged?” I inquired quickly, eager to


learn the truth about her from this man, who was evidently
an old friend of the family.

“Never actually engaged. There have been one or two little


love-affairs, I’ve heard, but none of them was really
serious.”

“He’d be a lucky fellow who married her,” I remarked, still


striving to conceal the intense interest I felt.

“Lucky!” he echoed. “I should rather think so, in many


ways. It is impossible for a girl of her beauty and nobility of
character to go about without lots of fellows falling in love
with her. Yet I happen to know that she holds them all aloof,
without even a flirtation.”

I smiled at this assertion of his, and congratulated myself


that I was the only exception; for had she not expressed
pleasure at my companionship on her walks? But
recollecting her admission that the victim of the assassin’s
knife had been her lover, I returned to the subject, in order
to learn further facts.

“Who were the men with whom she had the minor love-
affairs—any one I know?” I inquired.
“I think not, because it all occurred before they returned to
live in England,” he answered.

“Then you knew them abroad?”

“Slightly. We met in a casual sort of way at Pau, on the


Riviera, and elsewhere.”

“Both mother and daughter are alike extremely pleasant,” I


said. “In high spirits Mrs Anson is sometimes almost as
juvenile as Mabel.”

“Quite so,” he laughed. “One would never believe that she’s


nearly sixty. She’s as vivacious and merry as a woman half
her age. I’ve myself been surprised at her sprightliness
often and often.”

Again and again I endeavoured to turn the conversation


back to the identity of Mabel’s former lover, but he either
did not know or purposely refused to tell me. He spoke now
and then with an intentional vagueness, as though his
loyalty to the Ansons prevented him from betraying any
confidences reposed in him as a friend of the family.
Indeed, this cautiousness showed him to be a trustworthy
man, and his character became thereby strengthened in my
estimation. On first acquaintance I had instantly
experienced a violent aversion to him, but now, on this walk
together along the Fulham Road, I felt that we should
probably end by becoming friends.

He walked with long strides and a swinging, easy gait that


seemed almost military, while his air of careless merriment
as he laughed and joked, smoking the choice cigar which
the man had handed to him in the hall just before our
departure, gave him the aspect of an easy-going man-
about-town.
“I fully expect, my dear fellow,” he laughed—“I fully expect
that you’ll be falling in love with the pretty Mabel if you’re in
her company very much.”

“You’re chaffing,” I protested, echoing his laugh.

“Not at all,” he asserted. “Only take care. Love-making with


her is a dangerous pastime—devilish dangerous, I assure
you.”

“Dangerous to the man’s heart—eh?”

“Yes,” he responded in a vague tone, glancing at me


curiously; “if you like to put it in that way.”

We had passed from the Fulham Road into the King’s Road,
Chelsea, and at that moment he halted suddenly at the
corner of a street of high, regularly built houses, most of
which were in darkness, saying—“I live down here. Come in
and have a final whisky and soda with me; then you can
take a cab back to the Strand. There are cabs all night on
the rank in Sloane Square.”

“I fear it’s too late,” I protested, glancing at my watch, and


finding it past one o’clock.

“No, no, my dear fellow, come along,” he urged. “You’ll want


a drink before you get home;” and, thus persuaded, I
accompanied him up the street to one of the high houses,
each exactly similar to its neighbour, with a flight of
hearthstoned steps leading up to its front door, and a deep,
grimy basement protected by a few yards of iron railings.

In the hall, although the gas had been extinguished, there


remained a small hand-lamp alight, evidently placed there
for his use. This he took, and conducted me to a front
room, upon what the landlady of such a residence would
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.

More than just a book-buying platform, we strive to be a bridge


connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.

Join us on a journey of knowledge exploration, passion nurturing, and


personal growth every day!

ebookbell.com

You might also like