0% found this document useful (0 votes)
31 views55 pages

Instant Download Python in Practice Create Better Programs Using Concurrency Libraries and Patterns 1st Edition Mark Summerfield PDF All Chapters

Concurrency

Uploaded by

einatsergik
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
31 views55 pages

Instant Download Python in Practice Create Better Programs Using Concurrency Libraries and Patterns 1st Edition Mark Summerfield PDF All Chapters

Concurrency

Uploaded by

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

Download the full version of the ebook at

https://ebookgate.com

Python in Practice Create Better Programs


Using Concurrency Libraries and Patterns 1st
Edition Mark Summerfield

https://ebookgate.com/product/python-in-practice-
create-better-programs-using-concurrency-
libraries-and-patterns-1st-edition-mark-
summerfield/

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


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

Modern Tkinter for Busy Python Developers Quickly learn to


create great looking user interfaces for Windows Mac and
Linux using Python s standard GUI toolkit 3rd Edition Mark
Roseman
https://ebookgate.com/product/modern-tkinter-for-busy-python-
developers-quickly-learn-to-create-great-looking-user-interfaces-for-
windows-mac-and-linux-using-python-s-standard-gui-toolkit-3rd-edition-
mark-roseman/
ebookgate.com

Kivy Interactive Applications and Games in Python 2nd


Edition Create responsive cross platform UI UX
applications and games in Python using the open source
Kivy library Roberto Ulloa
https://ebookgate.com/product/kivy-interactive-applications-and-games-
in-python-2nd-edition-create-responsive-cross-platform-ui-ux-
applications-and-games-in-python-using-the-open-source-kivy-library-
roberto-ulloa/
ebookgate.com

Rapid GUI Programming with Python and Qt The Definitive


Guide to PyQt Programming paperback 1st Edition
Summerfield
https://ebookgate.com/product/rapid-gui-programming-with-python-and-
qt-the-definitive-guide-to-pyqt-programming-paperback-1st-edition-
summerfield/
ebookgate.com

Higher Order Perl Transforming Programs with Programs 2nd


Edition Mark Jason Dominus

https://ebookgate.com/product/higher-order-perl-transforming-programs-
with-programs-2nd-edition-mark-jason-dominus/

ebookgate.com
Digital Libraries Integrating Content and Systems 1st
Edition Mark V. Dahl

https://ebookgate.com/product/digital-libraries-integrating-content-
and-systems-1st-edition-mark-v-dahl/

ebookgate.com

Object Oriented JavaScript Create scalable reusable high


quality JavaScript applications and libraries 1st Edition
Stoyan Stefanov
https://ebookgate.com/product/object-oriented-javascript-create-
scalable-reusable-high-quality-javascript-applications-and-
libraries-1st-edition-stoyan-stefanov/
ebookgate.com

Learning BeagleBone Python Programming Unleash the


potential of BeagleBone using Python 1st Edition Hiam

https://ebookgate.com/product/learning-beaglebone-python-programming-
unleash-the-potential-of-beaglebone-using-python-1st-edition-hiam/

ebookgate.com

Sankara Nethralaya clinical practice patterns in


ophthalmology 1st Edition Badrinath

https://ebookgate.com/product/sankara-nethralaya-clinical-practice-
patterns-in-ophthalmology-1st-edition-badrinath/

ebookgate.com

Python Text Processing with NLTK 2 0 Cookbook Over 80


Practical Recipes for Using Python s NLTK Suite of
Libraries to Maximize Your Natural Language Processing
Capabilities 2. ed Edition Fattohi
https://ebookgate.com/product/python-text-processing-with-
nltk-2-0-cookbook-over-80-practical-recipes-for-using-python-s-nltk-
suite-of-libraries-to-maximize-your-natural-language-processing-
capabilities-2-ed-edition-fattohi/
ebookgate.com
Python in Practice
Developer’s Library Series

Visit developers-library.com for a complete list of available products

he Developer’s Library Series from Addison-Wesley provides


T 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 practitioners who are exceptionally skilled at organizing
and presenting information in a way that’s useful for other programmers.

Developer’s Library books cover a wide range of topics, from open-


source programming languages and databases, Linux programming,
Microsoft, and Java, to Web development, social networking platforms,
Mac/iPhone programming, and Android programming.
Python in Practice
Create Better Programs Using
Concurrency, Libraries, and Patterns

Mark Summerfield

Upper Saddle River, NJ · Boston · Indianapolis · San Francisco


p New York · Toronto · Montreal · London · Munich · Paris · Madrid p
Capetown · Sydney · Tokyo · Singapore · Mexico City
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.
The publisher offers excellent discounts on this book when ordered in quantity for bulk purchases
or special sales, which may include electronic versions and/or custom covers and content particular
to your business, training goals, marketing focus, and branding interests. For more information,
please contact:
U.S. Corporate and Government Sales
(800) 382-3419
corpsales@pearsontechgroup.com
For sales outside the United States, please contact:
International Sales
international@pearsoned.com
Visit us on the Web: informit.com/aw
Library of Congress Control Number: 2013942956
Copyright © 2014 Qtrac Ltd.
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 likewise. To obtain permission to use material from this work, please
submit a written request to Pearson Education, Inc., Permissions Department, One Lake Street, Upper
Saddle River, New Jersey 07458, or you may fax your request to (201) 236-3290.
ISBN-13: 978-0-321-90563-5
ISBN-10: 0-321-90563-6
Text printed in the United States on recycled paper at RR Donnelley in Crawfordsville, Indiana.
First printing, August 2013
This book is dedicated to
free and open-source software contributors
everywhere—your generosity benefits us all.
This page intentionally left blank
Contents at a Glance
Contents .......................................................... ix

Foreword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Chapter 1. Creational Design Patterns in Python . . . . . . . . . . . . . . . . 5

Chapter 2. Structural Design Patterns in Python . . . . . . . . . . . . . . . . 29

Chapter 3. Behavioral Design Patterns in Python .............. 73

Chapter 4. High-Level Concurrency in Python . . . . . . . . . . . . . . . . . . 141

Chapter 5. Extending Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179

Chapter 6. High-Level Networking in Python . . . . . . . . . . . . . . . . . . . . 203

Chapter 7. Graphical User Interfaces with Python and Tkinter 231

Chapter 8. OpenGL 3D Graphics in Python . . . . . . . . . . . . . . . . . . . . . . 263

Appendix A. Epilogue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283

Appendix B. Selected Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289

www.qtrac.eu/pipbook.html
This page intentionally left blank
Contents
Foreword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Chapter 1. Creational Design Patterns in Python . . . . . . . . . . . . . . . . 5


1.1. Abstract Factory Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.1. A Classic Abstract Factory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1.2. A More Pythonic Abstract Factory . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2. Builder Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.3. Factory Method Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.4. Prototype Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.5. Singleton Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

Chapter 2. Structural Design Patterns in Python . . . . . . . . . . . . . . . . 29


2.1. Adapter Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.2. Bridge Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.3. Composite Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
2.3.1. A Classic Composite/Noncomposite Hierarchy . . . . . . . . . . . . 41
2.3.2. A Single Class for (Non)composites . . . . . . . . . . . . . . . . . . . . . . 45
2.4. Decorator Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
2.4.1. Function and Method Decorators . . . . . . . . . . . . . . . . . . . . . . . . 48
2.4.2. Class Decorators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.4.2.1. Using a Class Decorator to Add Properties . . . . . . . . . . 57
2.4.2.2. Using a Class Decorator Instead of Subclassing . . . . . . 58
2.5. Façade Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
2.6. Flyweight Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
2.7. Proxy Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

Chapter 3. Behavioral Design Patterns in Python . . . . . . . . . . . . . . . . 73


3.1. Chain of Responsibility Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
3.1.1. A Conventional Chain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
3.1.2. A Coroutine-Based Chain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
3.2. Command Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

ix
3.3. Interpreter Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
3.3.1. Expression Evaluation with eval() . . . . . . . . . . . . . . . . . . . . . . . . 84
3.3.2. Code Evaluation with exec() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
3.3.3. Code Evaluation Using a Subprocess . . . . . . . . . . . . . . . . . . . . 91
3.4. Iterator Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
3.4.1. Sequence Protocol Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
3.4.2. Two-Argument iter() Function Iterators . . . . . . . . . . . . . . . . . . 96
3.4.3. Iterator Protocol Iterators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
3.5. Mediator Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
3.5.1. A Conventional Mediator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
3.5.2. A Coroutine-Based Mediator . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
3.6. Memento Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
3.7. Observer Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
3.8. State Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
3.8.1. Using State-Sensitive Methods . . . . . . . . . . . . . . . . . . . . . . . . . . 114
3.8.2. Using State-Specific Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
3.9. Strategy Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
3.10. Template Method Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
3.11. Visitor Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
3.12. Case Study: An Image Package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
3.12.1. The Generic Image Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
3.12.2. An Overview of the Xpm Module . . . . . . . . . . . . . . . . . . . . . . . . 135
3.12.3. The PNG Wrapper Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

Chapter 4. High-Level Concurrency in Python . . . . . . . . . . . . . . . . . . 141


4.1. CPU-Bound Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
4.1.1. Using Queues and Multiprocessing . . . . . . . . . . . . . . . . . . . . . . 147
4.1.2. Using Futures and Multiprocessing . . . . . . . . . . . . . . . . . . . . . . 152
4.2. I/O-Bound Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
4.2.1. Using Queues and Threading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
4.2.2. Using Futures and Threading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
4.3. Case Study: A Concurrent GUI Application . . . . . . . . . . . . . . . . . . . . 164
4.3.1. Creating the GUI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
4.3.2. The ImageScale Worker Module . . . . . . . . . . . . . . . . . . . . . . . . . . 173
4.3.3. How the GUI Handles Progress . . . . . . . . . . . . . . . . . . . . . . . . . . 175
4.3.4. How the GUI Handles Termination . . . . . . . . . . . . . . . . . . . . . . 177

x
Chapter 5. Extending Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
5.1. Accessing C Libraries with ctypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
5.2. Using Cython . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
5.2.1. Accessing C Libraries with Cython . . . . . . . . . . . . . . . . . . . . . . 188
5.2.2. Writing Cython Modules for Greater Speed . . . . . . . . . . . . . . 193
5.3. Case Study: An Accelerated Image Package . . . . . . . . . . . . . . . . . . . . 198

Chapter 6. High-Level Networking in Python . . . . . . . . . . . . . . . . . . . . 203


6.1. Writing XML-RPC Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
6.1.1. A Data Wrapper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
6.1.2. Writing XML-RPC Servers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
6.1.3. Writing XML-RPC Clients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
6.1.3.1. A Console XML-RPC Client . . . . . . . . . . . . . . . . . . . . . . . . 210
6.1.3.2. A GUI XML-RPC Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
6.2. Writing RPyC Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
6.2.1. A Thread-Safe Data Wrapper . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
6.2.1.1. A Simple Thread-Safe Dictionary . . . . . . . . . . . . . . . . . . 221
6.2.1.2. The Meter Dictionary Subclass . . . . . . . . . . . . . . . . . . . . . . 224
6.2.2. Writing RPyC Servers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
6.2.3. Writing RPyC Clients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
6.2.3.1. A Console RPyC Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
6.2.3.2. A GUI RPyC Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228

Chapter 7. Graphical User Interfaces with Python and Tkinter 231


7.1. Introduction to Tkinter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
7.2. Creating Dialogs with Tkinter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
7.2.1. Creating a Dialog-Style Application . . . . . . . . . . . . . . . . . . . . . . 237
7.2.1.1. The Currency Application’s main() Function . . . . . . . . 238
7.2.1.2. The Currency Application’s Main.Window Class . . . . 239
7.2.2. Creating Application Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
7.2.2.1. Creating Modal Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
7.2.2.2. Creating Modeless Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . 250
7.3. Creating Main-Window Applications with Tkinter . . . . . . . . . . . . 253
7.3.1. Creating a Main Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
7.3.2. Creating Menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
7.3.2.1. Creating a File Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
7.3.2.2. Creating a Help Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
7.3.3. Creating a Status Bar with Indicators . . . . . . . . . . . . . . . . . . . . 260

xi
Chapter 8. OpenGL 3D Graphics in Python . . . . . . . . . . . . . . . . . . . . . . 263
8.1. A Perspective Scene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264
8.1.1. Creating a Cylinder with PyOpenGL . . . . . . . . . . . . . . . . . . . . 265
8.1.2. Creating a Cylinder with pyglet . . . . . . . . . . . . . . . . . . . . . . . . . . 270
8.2. An Orthographic Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
8.2.1. Drawing the Board Scene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
8.2.2. Handling Scene Object Selection . . . . . . . . . . . . . . . . . . . . . . . . 277
8.2.3. Handling User Interaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280

Appendix A. Epilogue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283

Appendix B. Selected Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289

xii
Foreword to Python in Practice
I have been building software with Python for 15 years in various application
areas. Over that time I have seen our community mature and grow consider-
ably. We are long past the days of having to “sell” Python to our managers in
order to be able to use it in work-related projects. Today’s job market for Python
programmers is strong. Attendance at Python-related conferences is at an all
time high, for regional conferences as well as the big national and international
events. Projects like OpenStack are pushing the language into new arenas and
attracting new talent to the community at the same time. As a result of the ro-
bust and expanding community, we have more and better options for books about
Python than ever before.
Mark Summerfield is well known in the Python community for his techni-
cal writing about Qt and Python. Another of Mark’s books, Programming in
Python 3, is at the top of my short list of recommendations for learning Python,
a question I am asked frequently as the organizer of the user group in Atlanta,
Georgia. This new book will also go on my list, but for a somewhat different
audience.
Most programming books fall at either end of a spectrum that ranges from basic
introductions to a language (or programming in general) to more advanced books
on very focused topics like web development, GUI applications, or bioinformatics.
As I was writing The Python Standard Library by Example, I wanted to appeal
to readers who fall into the gap between those extremes—established program-
mers and generalists, both familiar with the language but who want to enhance
their skills by going beyond the basics without being restricted to a specific ap-
plication area. When my editor asked me to review the proposal for Mark’s book,
I was pleased to see that Python in Practice is designed for the same types of
readers.
It has been a long time since I have encountered an idea in a book that was im-
mediately applicable to one of my own projects, without it being tied to a specific
framework or library. For the past year I have been working on a system for me-
tering OpenStack cloud services. Along the way, the team realized that the data
we are collecting for billing could be useful for other purposes, like reporting and
monitoring, so we designed the system to send it to multiple consumers by pass-
ing the samples through a pipeline of reusable transformations and publishers.
At about the same time that the code for the pipeline was being finalized, I was
also involved in the technical review for this book. After reading the first few
sections of the draft for Chapter 3, it became clear that our pipeline implemen-
tation was much more complicated than necessary. The coroutine chaining tech-
nique Mark demonstrates is so much more elegant and easy to understand that

xiii
I immediately added a task to our roadmap to change the design during the next
release cycle.
Python in Practice is full of similarly useful advice and examples to help you
improve your craft. Generalists like me will find introductions to several inter-
esting tools that may not have been encountered before. And whether you are
already an experienced programmer or are making the transition out of the
beginner phase of your career, this book will help you think about problems
from different perspectives and give you techniques to create more effective so-
lutions.

Doug Hellmann
Senior Developer, DreamHost
May 2013

xiv
Introduction to Python in Practice
This book is aimed at Python programmers who want to broaden and deepen
their Python knowledge so that they can improve the quality, reliability, speed,
maintainability, and usability of their Python programs. The book presents
numerous practical examples and ideas for improved Python programming.
The book has four key themes: design patterns for coding elegance, improved
processing speeds using concurrency and compiled Python (Cython), high-level
networking, and graphics.
The book Design Patterns: Elements of Reusable Object-Oriented Software (see
the Selected Bibliography for details; ➤ 285) was published way back in 1995,
yet still exerts a powerful influence over object-oriented programming practices.
Python in Practice looks at all of the design patterns in the context of Python,
providing Python examples of those that are useful, as well as explaining why
some are irrelevant to Python programmers. These patterns are covered in
Chapter 1, Chapter 2, and Chapter 3.
Python’s GIL (Global Interpreter Lock) prevents Python code from executing on
more than one processor core at a time.★ This has led to the myth that Python
can’t do threading or take advantage of multi-core hardware. For CPU-bound
processing, concurrency can be done using the multiprocessing module, which
is not limited by the GIL and can take full advantage of all the available cores.
This can easily achieve the speedups we would expect (i.e., roughly proportional
to the number of cores). For I/O-bound processing we can also use the multipro-
cessing module—or we can use the threading module or the concurrent.futures
module. If we use threading for I/O-bound concurrency, the GIL’s overhead is
usually dominated by network latency and so may not be an issue in practice.
Unfortunately, low- and medium-level approaches to concurrency are very error-
prone (in any language). We can avoid such problems by avoiding the use of ex-
plicit locks, and by making use of Python’s high-level queue and multiprocessing
modules’ queues, or the concurrent.futures module. We will see how to achieve
significant performance improvements using high-level concurrency in Chap-
ter 4.
Sometimes programmers use C, C++, or some other compiled language because
of another myth—that Python is slow. While Python is in general slower
than compiled languages, on modern hardware Python is often more than fast


This limitation applies to CPython—the reference implementation that most Python programmers
use. Some Python implementations don’t have this constraint, most notably, Jython (Python
implemented in Java).

1
2 Introduction

enough for most applications. And in those cases where Python really isn’t fast
enough, we can still enjoy the benefits of programming in Python—and at the
same time have our code run faster.
To speed up long-running programs we can use the PyPy Python interpreter
(pypy.org). PyPy has a just-in-time compiler that can deliver significant
speedups. Another way to increase performance is to use code that runs as fast
as compiled C; for CPU-bound processing this can comfortably give us 100 ×
speedups. The easiest way to achieve C-like speed is to use Python modules
that are already written in C under the hood: for example, use the standard
library’s array module or the third-party numpy module for incredibly fast and
memory-efficient array processing (including multi-dimensional arrays with
numpy). Another way is to profile using the standard library’s cProfile module
to discover where the bottlenecks are, and then write any speed-critical code in
Cython—this essentially provides an enhanced Python syntax that compiles
into pure C for maximum runtime speed.
Of course, sometimes the functionality we need is already available in a C or
C++ library, or a library in another language that uses the C calling convention.
In most such cases there will be a third-party Python module that provides ac-
cess to the library we require—these can be found on the Python Package In-
dex (PyPI; pypi.python.org). But in the uncommon case that such a module isn’t
available, the standard library’s ctypes module can be used to access C library
functionality—as can the third-party Cython package. Using preexisting C li-
braries can significantly reduce development times, as well as usually providing
very fast processing. Both ctypes and Cython are covered in Chapter 5.
The Python standard library provides a variety of modules for networking,
from the low-level socket module, to the mid-level socketserver module, up
to the high-level xmlrpclib module. Although low- and mid-level networking
makes sense when porting code from another language, if we are starting out in
Python we can often avoid the low-level detail and just focus on what we want
our networking applications to do by using high-level modules. In Chapter 6
we will see how to do this using the standard library’s xmlrpclib module and the
powerful and easy-to-use third-party RPyC module.
Almost every program must provide some kind of user interface so that the
program can determine what work it must do. Python programs can be writ-
ten to support command-line user interfaces, using the argparse module, and
full-terminal user interfaces (e.g., on Unix using the third-party urwid pack-
age; excess.org/urwid). There are also a great many web frameworks—from
the lightweight bottle (bottlepy.org) to heavyweights like Django (www.django-
project.com) and Pyramid (www.pylonsproject.org)—all of which can be used to
provide applications with a web interface. And, of course, Python can be used to
create GUI (graphical user interface) applications.
Introduction 3

The death of GUI applications in favor of web applications is often reported—


and still hasn’t happened. In fact, people seem to prefer GUI applications to
web applications. For example, when smartphones became very popular early in
the twenty-first century, users invariably preferred to use a purpose-built “app”
rather than a web browser and web page for things they did regularly. There
are many ways to do GUI programming with Python using third-party packages.
However, in Chapter 7 we will see how to create modern-looking GUI applica-
tions using Tkinter, which is supplied as part of Python’s standard library.
Most modern computers—including laptops and even smartphones—come
equipped with powerful graphics facilities, often in the form of a separate GPU
(Graphics Processing Unit) that’s capable of impressive 2D and 3D graphics.
Most GPUs support the OpenGL API, and Python programmers can get access
to this API through third-party packages. In Chapter 8, we will see how to make
use of OpenGL to do 3D graphics.
The purpose of this book is to illustrate how to write better Python applications
that have good performance and maintainable code, and are easy to use. This
book assumes prior knowledge of Python programming and is intended to be the
kind of book people turn to once they’ve learned Python, whether from Python’s
documentation or from other books—such as Programming in Python 3, Second
Edition (see the Selected Bibliography for details; ➤ 287). The book is designed
to provide ideas, inspiration, and practical techniques to help readers take their
Python programming to the next level.
All the book’s examples have been tested with Python 3.3 (and where possible
Python 3.2 and Python 3.1) on Linux, OS X (in most cases), and Windows (in
most cases). The examples are available from the book’s web site, www.qtrac.eu/
pipbook.html, and should work with all future Python 3.x versions.

Acknowledgments

As with all my other technical books, this book has greatly benefited from the
advice, help, and encouragement of others: I am very grateful to them all.
Nick Coghlan, a Python core developer since 2005, provided plenty of construc-
tive criticism, and backed this up with lots of ideas and code snippets to show
alternative and better ways to do things. Nick’s help was invaluable throughout
the book, and particularly improved the early chapters.
Doug Hellmann, an experienced Python developer and author, sent me lots of
useful comments, both on the initial proposal, and on every chapter of the book
itself. Doug gave me many ideas and was kind enough to write the foreword.
Two friends—Jasmin Blanchette and Trenton Schulz—are both experienced
programmers, and with their widely differing Python knowledge, they are
ideal representatives of many of the book’s intended readership. Jasmin and
4 Introduction

Trenton’s feedback has lead to many improvements and clarifications in the text
and in the examples.
I am glad to thank my commissioning editor, Debra Williams Cauley, who once
more provided support and practical help as the work progressed.
Thanks also to Elizabeth Ryan who managed the production process so well, and
to the proofreader, Anna V. Popick, who did such excellent work.
As always, I thank my wife, Andrea, for her love and support.
1 Creational Design
Patterns in Python

§1.1. Abstract Factory Pattern ➤ 5


§1.1.1. A Classic Abstract Factory ➤ 6
§1.1.2. A More Pythonic Abstract Factory ➤ 9
§1.2. Builder Pattern ➤ 11
§1.3. Factory Method Pattern ➤ 17
§1.4. Prototype Pattern ➤ 24
§1.5. Singleton Pattern ➤ 26

Creational design patterns are concerned with how objects are created. Nor-
mally we create objects by calling their constructor (i.e., calling their class ob-
ject with arguments), but sometimes we need more flexibility in how objects are
created—which is why the creational design patterns are useful.
For Python programmers, some of these patterns are fairly similar to each
other—and some of them, as we will note, aren’t really needed at all. This is be-
cause the original design patterns were primarily created for the C++ language
and needed to work around some of that language’s limitations. Python doesn’t
have those limitations.

1.1. Abstract Factory Pattern


The Abstract Factory Pattern is designed for situations where we want to create
complex objects that are composed of other objects and where the composed
objects are all of one particular “family”.
For example, in a GUI system we might have an abstract widget factory that
has three concrete subclass factories: MacWidgetFactory, XfceWidgetFactory, and
WindowsWidgetFactory, all of which provide methods for creating the same objects
(make_button(), make_spinbox(), etc.), but that do so using the platform-appropri-
ate styling. This allows us to create a generic create_dialog() function that takes
a factory instance as argument and produces a dialog with the OS X, Xfce, or
Windows look and feel, depending on which factory we pass it.

5
Another random document with
no related content on Scribd:
then try to convince each planet of its own peril, so they could look
to their own defenses."
Stan sneered. "You haven't been successful, have you?"
"What do you think would happen if we showed ourselves and set
down a ship?" she asked curtly. "Most of the planets would be
paralyzed with terror! They'd consider us suspect and they would
hate us because we were more advanced. I do what I can. I try to
convince a few. And when I do, they usually try to help." She looked
at him again and her face was sheer hate. "Patriotic men, Martin—
men that you've helped to slaughter!"
For a fraction of a second, she looked like she was going to break
down. Then her face hardened again. Her voice was husky.
"I've manned the barricades on a thousand different planets, Martin!
I've fought the Thuscans for as long as I can remember. Sometimes
I've succeeded, more often I've failed. And when I've failed, I've had
to run away." Her voice changed to steel. "But I'm not running
anymore. If I lose, I'm staying here."
"You picked the wrong person to give a speech to," Stan said coldly.
He started for the door and then stopped. "You said I was an
Aurelian, a human being. What did you mean by that?"
"You were born in this city 25 years ago," she said in a low voice.
"You worked here, your family lived here. You had a mother and a
brother named Larry. You were ... exceptional. All the indications
are, that you would have made a great man. You loved the world
and the people in it. When you were seventeen, you were kidnapped
by the Thuscans and conditioned to what you are now. They
intentionally made you lose your memory, so that you would have no
memories and no will—no will but theirs."
"I don't believe you," he said heavily.
"You don't want to." She paused. "You better leave, Martin. You
better go back to the marionette makers and the string pullers."
He took one last look, realizing that something inside him was
struggling to give the girl comfort, to say something that might help
her. Then he shrugged and walked out the door.
He was two blocks away before he realized that both he and the girl
could have killed each other at almost any time.
But neither of them had made any attempt to.

CHAPTER X

He was two men, after the meeting with the girl, Stanley Martin, the
loyal Thuscan agent who continued to mastermind the betrayal of a
world.
And Stanley Martin, the man who wondered at and was repelled by
his own action. The man to whom the city of Chicago was strangely
familiar. The man who distrusted Tanner and who knew there was a
reason for it. The man in whose mind small bits of memory kept
bobbing to the surface, like a ship that was breaking up beneath the
sea and planks and spars kept rising to the top.
He also knew that that way lay ... madness. Two minds could not
continue to dwell in the same body. He could not continually war
with himself. The weaker, the fainter of the two would have to die.
Which meant that the person who had brought his weaker memory
to the surface would have to die.
Avis was slated for death.
He worked at it consciously and carefully. One of the fusion
packages was planted in a small store in Chicago, near the
intersection of 63rd and Halsted. One of Avis' agents tried to pick it
up and was killed. Two more tried the next day—and failed.
The word filtered out that the package was a special package, that
its importance overshadowed that of other fusion packages. But no
more agents tried for it.
By the end of October, opposition had apparently dwindled and
faded. Avis had vanished from sight. There were reports that she
had been seen in Stockholm and once that she had been glimpsed in
a Moscow suburb. Then the reports ceased entirely.
Stan was not deceived. Avis would try once more, he thought. She
would try for the package in Chicago. So he prepared for her, for the
final ambush.
The 31st of October, agents were reported filtering down to the
intersection and Stan decided to step in personally.
He stepped out of the circle of shimmering light in an alley near 63rd
street. Nobody noticed him at all. People were streaming past him,
racing through the alley to get away from the intersection. Stan
grabbed a man running past him.
"What's going on?"
The man was sweating with fear, his eyes rolling wildly.
"Christ, Mister, don't go out there! They got guns that shoot flames
and there's fifty people lying dead in the intersection! All in a
minute, I'm walking past on my way to Sears and all of a sudden the
streets are loaded with corpses!"
Stan let him go and raced up the alleyway. He could hear the quiet,
singing noises of the heat guns and the rapid, spanging gunfire of
Avis' men. She had come out in the open, trying desperately to
convince the apes that they were threatened by alien groups. She
had turned off the time projector halfway through the battle and it
must have seemed like carnage had sprung up instantaneously.
There were at least two dozen crumpled figures lying on the
pavement near the intersection. Some were crisped to near ash and
others had been blasted with the spanging pellets. Two cars were
blazing furiously and the windows in Sears and Wieboldt's had been
shattered.
A pellet whizzed past his ear and he ducked low, glancing swiftly
around the intersection. A thin, violet beam was playing from a
doorway in Sears and he dodged towards it, ignoring the other
spanging projectiles that ripped through the air and caromed off the
building walls behind him.
Tanner was in the doorway, nursing a bleeding shoulder, his face
glowing with the joys of battle.
"Tanner, what happened?"
"She's playing it in the open," Tanner snarled. "She's trying to
convince the apes that way!"
She might succeed, Stan thought slowly, but it was more likely that
the apes would blame it on a gang war of some kind. They wouldn't
believe the truth. They wouldn't want to.
Tanner pointed down the street a block. "Cover it down there and
we'll try to drive them towards you!"
Stan raced down half a dozen doors, then suddenly stiffened. There
was the wail of sirens. And then the heavy chatter of a machine gun
and the drifting choking of tear gas.
The spanging sounds and the violet beams suddenly stilled and
figures slipped quietly from the buildings towards the side streets.
Stan hesitated and then started running, away from the intersection.
He collided with Avis when she darted from a doorway. The granite
face had broken and tears were streaking down it. Before he realized
it, he was holding her tightly around the shoulders while she sobbed
into his chest.
He had been fooling himself all along, he suddenly knew. He couldn't
kill her. He couldn't come anywhere near to it.
He didn't want to.
"In every game," he said quietly, "there has to be a side that wins
and a side that loses."
Her sobs broke off and she looked up at him, shaking her head to
clear the hair from her face.
"I'm not crying because I've lost," she said quietly. "I'm crying
because ... a brave man is dying! Because so many brave men have
died!" She paused and the lines of weariness etched themselves
back into her face. "I should have told you, Stan. I should have told
you long ago. Maybe it might have helped."
She pointed to the intersection. "He won't ... last long. Go out and
say good-bye."

He stared back at the intersection. It was quiet now, powdered


concrete dust settling slowly out of the air. Police were circling
among the quiet forms lying on the pavement while curious
onlookers began to form a ring around the corner.
He walked quietly back to the street.
"Over here, Stan." The voice was faint. "You better ... hurry!"
A figure was slumped by one of the cars, its whole left side a singed
and blackened mass of ash.
Stan walked over to him. The man coughed and spewed a gout of
red over the front of him. "We always wondered what had
happened, Stan ... Mom and me. And then Avis found me and told
me you had sold out." The low hacking cough again and a
spasmodic heaving of the chest. "N ... never believed it. You weren't
the type." His eyes closed in brief pain. "Told her that a hundred ... a
thousand times, I guess." He paused for a moment and Stan
thought he was gone. Then the eyes flickered open.
"I was g-gonna break the whole story in tomorrow's editions. Guess
... your man got wind of it."
Stan couldn't bring himself to look down at the left side where the
clothing was burned and where half of the waist was carbonized. He
knew Tanner's work with the heater and he knew how well the man
liked to see his victims squirm.
The cough started in again and suddenly the man was sitting up, his
face twisted with pain and tears. "Y-you don't even remember me! Y-
you d-don't even remember your own damned brother!"
And just before he died he said: "I'm s-sorry, Stan. God bless...."
And then he was gone and Stan knew that the man he was holding
was nothing more than dead clay. He crouched there, his face wet,
and the bits and tiny pieces of personality that had once been
Stanley Martin coalesced and recombined into the individual they
had been eight years before.
He stood up, the tears streaming down his face, and looked down at
his brother Larry. A flood of memories were surging back. The
games they had played, the arguments they had had, the way they
had stuck up for each other....
And he could remember that morning when he had been slugged
and the Thuscans had picked him up. Mr. Malcolm and Mr. Ainsworth
and Tanner and the knives and the machines that had broken his
spirit.
Somebody tapped him on the shoulder. A policeman had his
notebook out and was looking at him curiously.
"You knew this man?"
"Once," Stan said slowly. "A long, long time ago."
He turned and walked up the street.
"Hey, you can't go! We need your help for questioning!"
He had more important business, Stan thought. With Mr. Ainsworth
and Mr. Malcolm.
And his fellow renegade, Tanner.
Avis was waiting for him in the alley, standing in the shadows by the
circle of whirling black. Her face wasn't the collection of hard planes
and angles it usually was and he realized dimly there was a beauty
about her he had never appreciated before. A beauty and a certain
sympathy....
He stood helplessly and looked at her. There was nothing he could
say.
There was nothing to say. He had betrayed his world and she knew
it.
"It's not too late," she said quietly.
He shook his head. "It's all over but the gloating." He felt himself
start to shake. "My God, I've condemned a world to death!"
"You can stop it."
"There's no time!"
"There's four days."
Four days, he thought wildly. Four days in which to recover fifty
fusion packages hidden in cities that circled the globe. Four days in
which he had to baffle his own agents ... and Tanner.
"I'm only one man, Avis. I could try—but I wouldn't make it!"
"If you want help," she said, "all you have to do is ask."
She still had her own organization, Stan thought. It wasn't as large
as his own but its members were willing to die for a cause and they
were brave and courageous. They didn't have the advantage of the
transport-hoops, but then they were already spread out around the
globe. It would be easy for Avis to communicate with them.
All he had to do was to give her the locations. And then, between
himself and her agents....
It might be possible at that.
"All right," he said grimly. "Let's try it." He checked his heat gun and
the two of them stepped through the shimmering haze....
... into the apartment in Bristol. He cautioned Avis to be quiet, and
then opened the door silently into the living room. Tanner wasn't
there but his lieutenant, Langerman, was. A small, wiry man with a
rodent's face and sliding eyes who preferred looking at the small of a
man's back rather than looking him straight in the eyes.
It had been necessary for Tanner and he to include one man in their
confidence, one man who would hold down the fort in Bristol and
watch the panels that marked the location of the fifty fusion
packages and the agents.
Langerman was sitting by the fusion package panel, reading a
newspaper.
He looked up when Stan stepped into the room. "How's it going,
boss?"
"It's going all right," Stan said casually. He reached into his pocket
for some money. "How about going down to the corner and having
some lunch sent up? Anything that looks good."

Langerman grabbed the coin, shrugged, and sauntered towards the


door. "Sure thing. Sandwiches and tea."
As soon as he was gone, Stan motioned Avis into the room and
started writing down the exact locations of the fusion packages.
Suddenly there was a voice behind him.
"Hey, what's going on? How'd the chick get in?"
Langerman had come back, his shirt faintly spattered with rain
drops. He had gotten as far as the front door, Stan thought,
discovered the state of the weather, and come back for a rain coat.
Nothing was going right....
It was too late for explanations. Langerman's hand had snaked
beneath his suit coat and come out with a small pistol.
"Tanner would like to hear about this," he said, his eyes narrow.
He should have thought of that long ago, Stan thought coldly.
Tanner hadn't trusted him, never had. Tanner had watched him. And
when Tanner wasn't around to do the watching, he had made sure
that somebody else was.
He didn't argue. He straightened out and dove for Langerman's legs.
There was a sharp report and a splintering sound behind him and
then Langerman was down, frantically trying to hit Stan in the face
with the pistol butt.
Stan rolled him violently against the wall and grabbed for the hand
that held the pistol. He caught it and tried to force it back. The two
arms wavered, then Langerman began to give a little, his arm
moving slowly back.
A world was in the balance, Stan thought grimly, and with a surge of
strength he had the pistol. He slashed at Langerman's head and the
little man went limp.
He stood up and thrust the list into Avis' hand. "There it is—all fifty.
I've marked the ones I'll try to work myself."
She took the list and started back to the whirling circle.
"We'll meet again?" he pleaded.
"Right here," she said calmly. "On November 4th."
He watched her disappear, then worked the dials for another
destination and stepped through to the unknown.
He had four days, he thought, in which to save a world.
Four short days.
CHAPTER XI

The night clouds rolled across the steeples of Bristol and the muffled
voice of a church clock somberly rolled across the city, striking the
hour of ten. The hush of a chill autumn night lay across the city,
mantling the fog that started to deepen in the city streets.
In a small apartment on Regent street, a box-like machine sat
quietly in a corner, staring at the growing gloom with fifty red,
unwinking eyes.
At five minutes after the hour, there was a flickering and then there
were only forty-nine. By eleven o'clock, the eyes had been cut down
to forty-six.
The evening of the first, there were only thirty-nine.
By the third, there was only a dozen. And every hour that went by
saw another light wink out....
He stood in a Moscow subway station, watching the trains thunder
past and keeping an eye on a trash can in a little niche near an
elaborate mosaic of Malenkov. None of the comrades, he thought,
would think of depositing litter near the mosaic of the leader and so
the can had never been used.
And since the cleaners knew it was never used, there was no earthly
reason why it should have to be disturbed and emptied. So the can
sat there and had never been touched.
Except once.
For a moment the platform was deserted and Stan walked rapidly
back to the can. A moment later he held the fusion package in his
hand....
Somebody barked something at him and he looked up, startled.
A few yards away, there was a man in the uniform of the people's
police. He could have been hiding for any one of a number of
reasons, Stan thought. He could have been watching for petty
thievery or perhaps there had been a drive against littering the
platforms.
But it didn't matter why he was there. The point was he was asking
questions in Russian and Stan couldn't answer him.
Another train roared in and people poured out of it, crowding
together on the platform. Stan turned and darted for a washroom,
breaking the wrappings on the fusion package as he ran. A moment
later he had snapped the detonating wires and broken the delicate,
clockwork mechanism and the almost infinitesimally small
transceiver.
He threw the remains of the package under the wheels of the train
at the same time a pistol shot roared above his head, chipping off
some of the tile of the ceiling.
Then he had made it to the washroom door, passed his hand over a
brass plaque, and darted through the circle of black that appeared
into....
... a dark corner of a bazaar in Damascus.
The bazaar stretched down both sides of the street, terminating
against a mosque at one end. There were small, open shops that
sold copperware and incense burners and large metal dishes,
ornately tooled. There were tables and boxes of elaborate mosaic
work—tables with veneers of rare wood and inlaid with mother of
pearl. There were small restaurants and notion stores and shops that
displayed bolt after bolt of silk and brocade.

Stan watched the people wandering past, then brushed past a small
native boy begging for coins, and walked into one of the silk shops.
"Yes, M'sieur?"
"You're holding a bolt of brocade for a Mr. Liebman. May I see it
please?" Stan flashed a card.
The little clerk waddled to the back of the store and returned with a
small bolt of silk. Stan reached for it but the small man held it back.
"You are Mr. Liebman?"
Stan was sweating. "I'm a friend of his."
"I'm sorry, M'sieur. I was told not to release this to anybody but Mr.
Liebman."
The little man wanted to stand and argue while the world went up in
flames, Stan thought. He pulled out his wallet and slid a five dollar
bill across the counter.
"I don't think Mr. Liebman would want this quite as much as I
would."
The little man was not convinced. "Perhaps not but...."
Stan thrust out the flat of his left hand and pushed the clerk back
against the shelves. Bolts of cloth rippled down from them and Stan
had to dig beneath them to get the one he wanted.
A moment to open the bolt and cut the wires of the package and
then he was out in the street once more, the clerk's shrill, indignant
screams echoing after him.
He raced to the end of the street, near the mosque, for the dark
corner that looked a little too dark and a little too glossy and then....
... out again in a small street a block from the Vatican in Rome. It
was early evening. Twelve more hours to go, he thought, for the last
one. That wouldn't take long and he could double-check any that
Avis' agents might have missed.
He hailed a taxi and sped out to the ruins of the old Forum. He
waited until the taxi had left and then walked over to the column of
Trajan—the tall, marble column that had been erected in order to
commemorate the victories and the accomplishments of the old
Roman emperor. He vaulted the low iron fence that surrounded the
column and broke the lock on the door that led to an interior
stairway.
The package was still in its niche at the top of the stairs. Stan tore at
the wrappings and pulled, its teeth, then crushed the package in his
hands. That was the end of....
There was the sound of racing footsteps up the winding stairwell.

He flattened himself against the wall until they came into view, then
launched himself down the stairs, landing squarely on the chest of a
burly man so they both rolled down the steep flight of stairs.
Tanner had finally gotten wind of what was going on, Stan thought
sharply. But it was too late to do anything about it now. The invasion
had been set, you couldn't stop a fleet once it rolled into motion.
The overconfident Thuscans would land—to discover to their
shocked surprise that there was organized resistance.
Mr. Ainsworth's "apes" wouldn't be a pushover....
"Bastarde...."
The burly man wasn't alone. There was another at the bottom of the
stairs. Stan twisted his body, holding the first Italian in front of him.
There was a pistol shot and the sound of a bullet smacking into solid
flesh. The man whom Stan held screamed shrilly, his eyes flaring
wide.
Then all three of them were down. Stan leaped for the door and
slammed it after him. A moment later he was sprinting through the
low midway of tumbled arches and forlorn columns of the glory that
had once been Rome.
He caught another taxicab by the Colliseum, slipped the driver the
contents of his wallet, and sagged against the cushions exhausted.
A shot shattered the rear window of the cab and he felt vainly in his
coat pocket for his heater. It must have fallen out during the long fall
down the flight of stairs, he thought. Which meant that he was
defenseless.
He left the cab a few doors down from the alley and sprinted into
the darkness, another shot whistling past his ear. He was almost up
to the circle of shining black when the bullet plowed into the fleshy
part of his back and he half stumbled, half fell into the pool of
whirling blackness....

CHAPTER XII

"You didn't succeed, Martin. Come on—wake up so I can tell it to


your face. You and the rest of the apes have lost forever!"
He stirred and gagged and then rolled on his side, feeling the pain
from his shoulder lance through his body. There had been the shot
and he had felt himself falling and then there had been a voice....
Tanner's voice.
His eyes jerked wide open and he sat up, wincing at another flash of
pain.
"Finally awake, are you?"
He turned. Tanner was on the small pedestal that held the hoop,
standing nonchalantly in front of the circle of whirling black.
"You'll be sorry you woke up, Martin. Frankly, I should think you
would be wishing you were dead." He half smiled to himself.
"There's knives in the kitchen, incidentally, in case you should want
to do something about it. I imagine you have quite a guilt complex."
Stan whipped his head around to look at the small box-like machine
that kept score of the fusion packages. Only one light was still lit.
The light for Chicago.
Tanner smiled lightly. "Don't think you've won just because there's
only one light left. Fifty fusion packages was our safety factor. We
actually only needed one."
Stan's face mirrored what he thought and Tanner read the look.
"That's right," he nodded. "Only one. We wanted to create panic and
one will do that. When it goes off, that's all we need. The rest of the
world will hear about it seconds later. And then the flight will be on."
He paused. "You don't think that people—anywhere—are going to
remain in their cities, do you? All the police, all the commissars in
existence, couldn't make them do that. And then the air fleets will
spring into action. One fleet because it demands vengeance, and the
other because the only defense is a good offense, as the ape
politicians are so fond of saying."
He shrugged. "You see? It really only takes one for disaster."
Stan gathered his muscles for one last lunge....
Tanner caught the movement and raised his eyebrows.
"You wouldn't want to do that, Martin. For one reason, I've got Avis.
And for another, it would be too late. The blast went off ten seconds
ago."
He waved and stepped into the blackness.
Stan reeled over to the set and dialed Chicago. The sheet of
blackness formed, wavered, and then faded back to the edges of the
hoop.
He had lost, Stan thought, dazed. The city he had been born and
raised in was one with the drifting atoms of the air.
Tanner had won, completely. And Tanner had Avis.
Stan huddled in the center of the room, his mind a melee of
flickering thoughts. Then a noise at the window caught his ear. The
noise of doors slamming and the starting of a thousand automobiles
and people running through the streets. He didn't bother to look—he
knew what it was.
The exodus of a billion people from ten thousand towns and cities
was on the way.
There was six hours to go before the start of the brief, abortive war.
Six hours before the air fleets would arrive at their destination.
A day later the Thuscan fleet would settle from the skies to begin
the mopping up operation, the operation that would change the face
of a green, water world to a world that would be another colony
planet for Thusca.
A world in which the human race would play no part.
And there was the matter of the girl....

The noise outside the street was a steady roar, now. The street was
gorged with people on foot and on bicycles and in automobiles,
fighting to get out of the city. He could hear screams and curses and
over all, the faint crackle of flames.
In a few hours, the city would be a roaring inferno, he thought.
There would be nobody left behind to put out the fires. And the
scene would be duplicated a thousand times over before the sun
went down.
And the next day there would be the final, terrible tempest when the
Thuscans arrived. When humanity would go out in a short, confused
struggle.
There was nothing left to do but prepare to die....
Then he thought again of Avis and knew there was one last, forlorn
chance.
He raced back to the communications room and pressed the
switches on the small television set with which he and Tanner used
to communicate with Mr. Ainsworth on the Thuscan flag ship.
Avis had mentioned that her own fleet was standing by. A small fleet
perhaps, but certainly not one without possibilities.
He waited a moment for the tubes to warm up, then dialed the
frequency Avis had once mentioned. There was a pause and the
screen grew bright. A face wavered on it for a moment and then
grew steady. It was the face of a middle-aged man dressed in a dull
blue uniform. His eyes looked like they had seen all there was to see
of both heaven and hell.
Stan explained the situation urgently. The face nodded acceptance
of what had happened.
"Can you get out of the city?"
The sounds outside were a steady roar now. Stan hesitated a
moment, then said yes.
"We'll try to pick you up. Take the main artery out of the city to the
small wooded park."
"What are you going to do?"
The lines in the man's face deepened. "Outside of pick you up,
there's nothing we can do."
Stan flicked off the switch and started for the door. So there was
nothing they could do. Nothing they could do to save a world or to
save Avis.
Well, that remained to be seen.

He opened the street door and was almost swept into the tightly
packed, fast moving throng. He stepped back into the doorway for a
moment, letting the fighting, struggling mob sweep by. A father held
a squawling baby high above his head. A woman was crying,
hugging a small bundle of clothes to her as she struggled on.
Suddenly she slipped and fainted and slid beneath the thousand feet
of the mob. Stan didn't see her reappear.
He closed the door and ran to the back. The alley was crowded but
not nearly so packed as the street.
Perhaps half an hour had passed since Tanner had appeared in the
hoop, he thought. He had five and a half hours to go before the
bombs started dropping.
His back pained him and he could feel the blood start to well where
he had been shot. He grimaced and struggled on. A man next to him
was lugging a small, portable radio and Stan could hear the
frightened announcer reading off the government's mobilization
orders and exhortations to remain calm.
They were useless, Stan thought bitterly. They could have no more
effect on the tidal waves of humanity leaving its cities than Xerxes
had on the ocean, when he had ordered it to be whipped. Humanity
was leaving its huddling places and there was nothing that could
stop them.
An hour later and he made two miles through the packed outskirts
of the city. The crowd was thinning now and he thought he could
make out the wooded sections of the park, not more than three or
four blocks ahead. It couldn't be too much longer, he thought. He
wasn't sure of how much more he could take....
His shirt was torn and the wound in his back was bleeding freely.
Worse than that had been the sights he had seen on the way—
women and children trampled underfoot, and the few neurotic souls
who had given up and taken the short way out by leaping from
windows.
It was slaughter, even without the war, he thought. Humanity was
destroying itself in senseless panic. And then he was in the wooded
area that had grown close to the city. He pushed through the brush
and trees until he found a small clearing. The mass of people
streamed past it, anxious to put miles between themselves and the
buildings that so obviously spelled destruction.
He had waited for perhaps an hour when a small life boat rocket put
down in the clearing. He looked at his watch before stepping aboard.
Time had narrowed to three hours.

CHAPTER XIII

The war rockets from Avis' home system of Aurelia stretched


through space like a thin, red string. There were more than a
hundred there, Stan thought, but he knew without asking that they
were hopelessly outnumbered by the Thuscan ships.
The small rocket maneuvered over the lead ship—a hatch slid back—
and the rocket settled slowly through the opening.
A moment later and Stan was in the main cabin, facing half a dozen
tired looking men wearing the same dull blue uniform as the man on
the screen. They were supposed to be fighting men, Stan thought,
but they didn't look the part.
They looked more like frightened civilians who had been drafted.
The man Stan had seen on the screen introduced himself as Elal and
smiled wryly.
"We're not the professionals you've associated with until lately,
Martin. Fighting is something new for us. It will be a while before we
achieve the hardened look of the warrior race."
His voice was soft and tired. The voice of a man who had lost his
spirit, who had ceased to hope.
"What's the situation?" Stan asked.
Elal shrugged. "You should have been able to size it up quickly. We
are outnumbered—about ten to one, I would say. We had been
hoping until the last minute that perhaps Avis would succeed, that
she would be able to prevent the subversion of the planet."
"Just what would that have accomplished?"
"You Terrans are not without the means of defense," Elal pointed
out. "In many ways you may be backward and primitive but you
have deadly weapons. And a planet, strongly organized for
resistance, would be very difficult for the Thuscans to take over.
They have never succeeded in storming one outright. They have
always had to rely on infiltration."
"Your weapons aren't puny either," Stan said. "You have the time
fields."
"They have limited application—they are good for only small fields
and only for short times. And the Thuscans have neutralizers."
Another man, who looked oddly familiar, spoke up.
"What's happened to Avis?"
Her father, Stan guessed shrewdly.
"She was captured by Tanner."
There was a short silence and the men looked oddly helpless.
"Well, what are you going to do?" Stan burst out. "You're the only
hope that's left!"
Elal shrugged. "What is there to do? We have you. Perhaps you will
be of help, if you can remember much of Thusca. So far as we
know, you are the only man who has been there and returned.
Outside of...." And then he broke it off.
"You're going to leave the world go by default?" Stan asked coldly.
"And Avis, too?"
The group of Aurelians looked annoyed. "What would you have us
do?" Elal asked. "We gambled and we lost. We are outnumbered ten
to one. And this is not the only world we have to worry about,
Martin. There are a thousand others."
"And you'll be outnumbered at each one, won't you?" Stan asked
grimly. "You'll be continually retreating but the odds will never get
any better. As your ring of defenses collapses and allows you to
concentrate more and more, the area the Thuscans have to
concentrate on will be steadily getting smaller. You have to make a
stand for it—why not here?"
"It wouldn't work. We would lose. And we're far too large a part of
our total fleet to take the risk."
They wanted to give up because it looked bad on paper, Stan
thought. They didn't want to see blood spilled, they didn't want to
get their fingers dirty.
"Where's the Thuscan fleet?"

The young man at the controls worked the dials of a screen which lit
up to a luminous black. There was the Earth at one end of the
screen—a green globe the size of a basketball—and then the star-
flecked, velvet sky.
Stan watched a small collection of brilliant lights move slowly across
the screen. The operator pressed another button and that segment
of the heavens suddenly leaped forward into the viewscreen. The
collection of lights swiftly evolved into the glowing, rod-like ships of
the Thuscans. They were arranged into a triangle, a large, reddish
colored ship at the apex.
Mr. Ainsworth would be on that ship, Stan thought. Mr. Ainsworth
and Mr. Malcolm and maybe even Tanner.
It was ... logical that Tanner would be there. His work on Earth was
done. And it was probable that Avis was on the ship with him. She
would be valuable as a hostage.
He stared thoughtfully at the screen. It wasn't a neat triangle, it
wasn't a really militaristic formation. The files of ships were a little
straggly, as if their commanders weren't really expecting any
opposition. From any quarter.
"We could go down," Stan said thoughtfully. "We could force the
lead ship to land in Europe. It would be Exhibit A, it would stop the
war. You would have time to make explanations and if I know the ...
apes ... they wouldn't be such pushovers after that."
"You think it would succeed?" one of the men asked sarcastically.
"There's always the element of surprise," Stan said bitingly. "It's
probably the last thing they would be expecting you to do." He
paused. "You say that you are outnumbered and your weapons are
not the best. Have you ever tried the oldest one of all—courage?"
There was a dead silence.
"You're being very inspirational," Elal said after a moment. "But I
don't think you're being very practical."
Stan glanced around the compartment. The pilot was young. He
looked expectant, and somewhat hopeful. He would be willing to
dare, Stan thought. The others had never fought a war, they didn't
know how.
Stan turned to the pilot. "Take it down—towards the lead ship in the
Thuscan Fleet!"
"How do we know he's changed?" a voice bleated. "Maybe he's still
in league with Thusca!"
Stan turned, the blue of a heat gun shining in his fist. "I have no
time to argue—but it's not true." To the pilot: "Take it down!"
"You forget that I'm the leader here," Elal said quietly.
"You've abdicated your position," Stan said softly. "A leader is a man
who can lead. You can't. I can." His eyes blazed.
"We're going down!"

CHAPTER XIV
They plummeted through space, towards the lead ship in the
Thuscan fleet that was circling ever closer to the planet below. Stan
glanced at his watch. Barely an hour remained before the planet
below would be fighting a hideous, futile battle.
Barely an hour left in which he had to accomplish the impossible.
"Look!" somebody shouted. "Look at the screen!"
Stan glanced at it briefly. There was the Thuscan fleet laid out below
—much nearer now—and the small, flashing dot that represented his
own craft.
Behind him, strung out like a lazy figure C, was the rest of the
Aurelian fleet. They were following the leader down, even though
they recognized the enormous odds at which they were going to be
fighting.
Courage, Stan thought, feeling something catch in his throat. The
unknown weapon.
But just how much could it accomplish?
"Contact in half a chrono," the pilot said.
Stan walked over to him.
"Show me how this works."
It was simple enough, Stan discovered. The firing studs for the
different, directional rockets could be played like the keys of a piano.
And the radar that indicated distance from another object was
accurate to the yard.
Stan studied the pilot for a minute, trying to guess at his reflexes.
"When we make contact, do exactly as I tell you."
He shifted his gaze to the viewscreen. The Thuscan fleet was much
nearer now, but the formation was changing slightly. The triangle
was more ragged, more uncertain looking. They weren't sure of
what was going to happen, Stan thought, and they were worried.
Which was just what he wanted.
"You'll kill us all!" a voice behind him screamed.
"Maybe I will," Stan mused softly. "I don't promise you a thing!"
They were brief miles away now.
"Fire left!"
The port rockets lifted the ship slightly and they flashed directly over
the Thuscan lead rocket, a bare half mile beneath them. The wash
from Stan's rockets flared lightly over the Thuscan ship and then
they were pulling away.
"Try again."
The pilot turned the rocket in a circle and headed back. Beneath
them, the lead Thuscan ship was belching flame and breaking out of
formation, trying desperately to get away from the insane men who
were bent on committing suicide.
Stan flashed them again, even closer. There was no place for the
Thuscan ship to go but down.

Stan laughed outright and drove it like a dog herding sheep,


hounding them too close for them to bring their weapons into play,
and daring death every time he drove at them.
He was courting death and he knew it. And didn't care. The minutes
were ticking slowly by and he knew that time was running out for
half a billion people on the green globe below.
He glanced again at the viewscreen. Space was a tangle of flaring
lights and rocket trails. But confused as the picture was, he knew
one thing. Surprise and courage had been the elements they
needed.
They were winning.
He turned to Elal. "Get the Thuscans on the viewscreen."
A moment later, the picture on the screen faded and another control
cabin faded in. The creature in the picture recognized Stan and a
moment later the sober face of Mr. Ainsworth was staring out at him.
"You shouldn't be doing this, Stan," Mr. Ainsworth said, his voice
sounding bewildered and hurt. "Is this the way you pay back
friendship? Is this how you repay hospitality?"
He could listen to the words and know they were lies. He could look
at Mr. Ainsworth and know what lay beneath that saint's face. But he
still wanted to believe. He wanted desperately to believe. To be told
by Mr. Ainsworth that all was forgiven.
His throat was dry and he was dripping sweat. His conditioning
wasn't going to disappear over-night, he knew. It would be a battle
all the time. And this was just the first round.
"I'm going to force down your ship and kill you," he said quietly. "But
first, we're going to play tag over every civilized capital on the globe.
We're going to let them know just what the story is. And then, if the
Thuscan fleet still wants to come in, they can go ahead and try it.
But I wouldn't advise it, Ainsworth! The apes won't be easy
pickings!"
He flicked off the set. They were in the atmosphere now and the air
was screaming past the hull. He could feel the temperature inside
the cabin rise and then the refrigeration went into action.
They rocketed over the ocean and then they were over London, a
bare five miles up. The ships and their exhaust were clearly visible to
the frightened millions camping outside the city.
Stan drove the Thuscans over Paris and Moscow and Tokyo and
Washington, timing his rocket blasts and forcing them whichever
way he wanted them to go. He threatened to crash them from above
if they tried to leave, and threatened to ram them from below if they
tried to land.
Governments watched, frightened at the scene and realized what
must be waiting out in space. Huge planes that had been winging
over arctic wastes and across vast stretches of sea suddenly got
crackling messages that forced them to turn abruptly in their courses
and head for the nearest air field—whether it was friend or late
enemy.
Far out in space, the void was filled with hulled ships and flaring
rockets that suddenly mushroomed into gigantic explosions. Down
below, Stan drove the Thuscan ship around the world and then
towards Europe again.
He finally forced it to crashland in the Tiergarten in evacuated Berlin.

His own ship landed a block away.


The dazed officers in the compartment looked at him for guidance
and he realized that he was still the leader, that they still didn't quite
know what to do.
"You'll go out that airlock and you'll fight them," he said crisply.
"Hand to hand, if you have to. But you'll have to fight them—and to
kill them." He strode to the airlock. "Good luck!"
There was no motion about the other rocket and he thought for a
frightening moment that everybody on board had been killed. Then
he realized that they were waiting for him to make a move, to show
himself for an easy target.
He found a hiding place behind a bit of rubble and adjusted the stud
on his heat gun.
They weren't going to stay in their ship long, he thought. He would
make them come out.
He turned the stud to high and aimed the gun at a port near the
control room. The crystal in the port colored, glowed, and suddenly
fused. Stan could dimly make out the control console and flashed his
heater at that. The violet beam touched the controls and they turned
red and fused. Then the beam caught a thin fuel line in the console
and there was a sudden spurt of white heat.
Seconds later, the fuel tanks erupted with a roar that showered bits
of red hot metal over the whole area.
A moment more, he thought....
The air about him was suddenly thick with lancing, violet beams and
he felt one touch him lightly on the shoulder, crisping the flesh and
setting his shirt on fire. He winced and beat out the flames, keeping
an eye on the hatch.
Then the hatch flew open and figures boiled out.
The slaughter was brief, and very thorough. But of all the creatures
that boiled out of the hatch, Stan didn't see the two he was looking
for.
When it was all over, he walked out to the field and glanced at the
bodies. There were none that looked like Tanner or—thank God—
Avis.
He was touching one body gingerly with his foot when the young
pilot ran up to him.
"There was no action on the other side of the ship, was there, sir?"
"No. Why?"
"One of the ports, sir—fused. And there were no flames near it!"
Stan started running for the other side of the ship. There was the
blasted port and then footsteps in the carbonized grass that had
been flamed when the ship had landed. He ran quickly over the
grass, following the footsteps, then glanced ahead into the city.
He caught one brief glimpse of them. Two figures disappearing
behind some rubble, running toward one of the side streets....
And the hoop that Stan knew was in an alley behind the Russian
owned and operated department store in the Eastern sector.
Stan dashed through the streets. They were two blocks ahead of
him—Tanner and a girl, whom he was half pushing, half pulling.
A beam flared above Stan's head and he ducked and zig-zagged
from one side of the street to the other.
The figures turned a corner and Stan fired one last, futile shot at
them.
When he finally turned into the street, there was nobody in sight—
only the whirling black velvet of the hoop.
He hesitated and then dove through it....
... to a street he had seen once before. The Street of Lepers in
Casablanca.
The street was deserted—there were no signs of either Tanner or
Avis. He walked slowly down the street, and then there was a
rustling noise behind them. He whirled, just in time to see Tanner
and Avis disappear into the hoop again.
He ran and plunged in after them. It was going to be difficult, he
thought. He would have to leave the vicinity of the hoop to look for
them. And once his back was turned, they would be going through
the hoop once more.

He caught a quick glimpse of Tanner in the deserted streets of


Barcelona, Spain. He almost ran into the two in the empty streets of
Shanghai. Madrid, Paris, Stuttgart, Leningrad, Los Angeles, Dallas—
the cities flashed by like a deck of cards that was flicked past his
eyes. The unending succession of black velvet hoops through which
he moved like a man traveling through an infinity of dimensions....
And then the apartment in Bristol and Tanner was there, waiting for
him. Simply standing against a table, waiting. Avis was in the far
corner, her face frightened and drawn.
Stan paused, eyeing the situation.
"It's been quite a chase, hasn't it?" Tanner asked.
Still the urbane Mr. Tanner, Stan thought.
"I caught you, though, didn't I?"
"It all depends on how you look at it. Perhaps I've caught you."
Tanner held an unfamiliar weapon in his hand. Stan looked at it
curiously and then knew exactly what it was. Tanner had gotten hold
of Avis' time pistol. He was going to kill him like William Clark had
been killed.
Tanner was going to age him a hundred years in a second.
"Think you'll get away with it, Tanner?"
"Why not? There's nobody to stop me!"
How many times had he died in the last eight years? Stan wondered.
How many times had his life been hanging by a thread, waiting for
somebody to cut it?
"Stan! Duck!"
Tanner had been distracted just long enough by the shout. Stan
dropped to the carpet and rolled against Tanner's legs. Then they
were both on the floor. Stan grabbed for the arm which still clung to
the time pistol. Tanner grunted and twisted and then....
Stan paled and almost gagged.
Tanner was flickering.
In the background, Avis screamed. And then Mr. Ainsworth was
looking at him.
"I'm your friend," the creature said weakly.
Stan weakened and almost let go.
"I'm your friend," the creature repeated softly, triumphantly. "I saved
your life, didn't I?"
He was lying in the alley again, back in Chicago, lying there hurt and
bleeding. And Mr. Ainsworth had come up to help him. Out of all the
millions of people in the city, it was only Mr. Ainsworth who had
helped.
"I'm your friend," the creature purred again.
That still, quiet morning when the chill air had hung heavy over the
city....
And then the conditioning was totally gone and Stan felt exultant.
He hadn't realized....
He gripped the arm harder and twisted and the time pistol went
skittering across the carpet.
Mr. Ainsworth looked surprised and faded back into Tanner. A
powerful, cold-eyed Tanner who suddenly wrenched free and bent
Stan under him. He reached for a water carafe from the table to
bring it down to smash Stan's skull.
Stan jerked his head to one side and doubled his legs under him and
lashed out with them, catching Tanner in the chest. Tanner
staggered backwards towards the hoop, his foot unintentionally
pressing the on switch. The circle of black started to build up.
The time pistol was only a few feet away. Stan snatched at it and
turned it on the still reeling Tanner. It caught the creature flush at
the same time as he toppled back through the black velvet circle.

You might also like