Download DevOps in Python: Infrastructure as Python, 2nd Edition Moshe Zadka ebook All Chapters PDF
Download DevOps in Python: Infrastructure as Python, 2nd Edition Moshe Zadka ebook All Chapters PDF
com
https://ebookmeta.com/product/devops-in-python-
infrastructure-as-python-2nd-edition-moshe-zadka/
OR CLICK HERE
DOWLOAD NOW
https://ebookmeta.com/product/devops-in-python-infrastructure-as-
python-2nd-edition-moshe-zadka-2/
ebookmeta.com
https://ebookmeta.com/product/patterns-and-practices-for-
infrastructure-as-code-with-examples-in-python-and-terraform-
meap-v08-rosemary-wang/
ebookmeta.com
https://ebookmeta.com/product/turmoil-a-scottish-medieval-romance-
crown-crosses-book-3-1st-edition-violet-malvik/
ebookmeta.com
https://ebookmeta.com/product/good-enough-mothers-practicing-nurture-
and-motherhood-in-chiapas-mexico-1st-edition-j-m-lopez/
ebookmeta.com
https://ebookmeta.com/product/philosophy-of-digital-currencies-a-
theory-of-monetizing-time-1st-edition-ugochukwu-chigoziem-ikpeazu/
ebookmeta.com
https://ebookmeta.com/product/probability-and-statistics-for-
economists-12th-edition-bruce-hansen/
ebookmeta.com
https://ebookmeta.com/product/huge-working-hero-hard-working-
hero-3-1st-edition-penny-wylder/
ebookmeta.com
DevOps in Python
Infrastructure as Python
Second Edition
Moshe Zadka
DevOps in Python: Infrastructure as Python
Moshe Zadka
Belmont, CA, USA
Introduction�����������������������������������������������������������������������������������������������������������xvii
Chapter 2: Packaging����������������������������������������������������������������������������������������������� 7
2.1 Virtual Environments��������������������������������������������������������������������������������������������������������������� 7
2.2 pip������������������������������������������������������������������������������������������������������������������������������������������� 9
2.3 Setup and Wheels����������������������������������������������������������������������������������������������������������������� 12
2.4 Binary Wheels����������������������������������������������������������������������������������������������������������������������� 16
2.5 m anylinux Wheels������������������������������������������������������������������������������������������������������������� 18
2.5.1 Self-Contained Wheels������������������������������������������������������������������������������������������������� 19
2.5.2 Portable Wheels������������������������������������������������������������������������������������������������������������ 19
2.5.3 manylinux Containers��������������������������������������������������������������������������������������������������� 20
2.5.4 Installing manylinux Wheels����������������������������������������������������������������������������������������� 20
2.6 tox���������������������������������������������������������������������������������������������������������������������������������������� 21
2.6.1 One Environment���������������������������������������������������������������������������������������������������������� 22
2.6.2 Multiple Environments�������������������������������������������������������������������������������������������������� 23
2.6.3 Multiple Differently Configured Environments�������������������������������������������������������������� 23
v
Table of Contents
Chapter 5: Testing��������������������������������������������������������������������������������������������������� 67
5.1 Unit Testing��������������������������������������������������������������������������������������������������������������������������� 67
5.2 Mocks, Stubs, and Fakes������������������������������������������������������������������������������������������������������ 72
5.3 Testing Files�������������������������������������������������������������������������������������������������������������������������� 73
vi
Table of Contents
vii
Table of Contents
viii
Table of Contents
ix
Table of Contents
Index��������������������������������������������������������������������������������������������������������������������� 231
x
About the Author
Moshe Zadka has been involved in the Linux community
since 1998, helping in Linux “installation parties.” He has
been programming Python since 1999 and has contributed
to the core Python interpreter. Moshe has been a DevOps/
SRE since before those terms existed, caring deeply about
software reliability, build reproducibility, and more. He has
worked in companies as small as three people and as big as
tens of thousands—and usually in a position where software
meets system administration.
xi
About the Technical Reviewer
Martyn Bristow is a software developer in the United
Kingdom. He began using Python as a researcher but is
now an experienced broad user of Python for data analysis,
software test automation, and DevOps. He currently builds
data analysis web apps in Python deployed to Kubernetes.
You can find Martyn on GitHub @martynbristow.
xiii
Acknowledgments
Thanks to my wife, Jennifer Zadka, without whose support I could not have written
this book.
Thanks to my parents, Yaacov and Pnina Zadka, who taught me how to learn.
Thanks to my advisor, Yael Karshon, who taught me how to write.
Thanks to Mahmoud Hashemi for inspiration and encouragement.
Thanks to Mark Williams for being there for me.
Thanks to Glyph Lefkowitz for teaching me about Python, programming, and being a
good person.
Thanks to Brennon Church and Andrea Ross, who supported my personal growth
and learning journey.
xv
Introduction
Python began as a language to automate an operating system: the Amoeba. A typical
Unix shell would be ill-suited since it had an API, not just textual file representations.
The Amoeba OS is a relic now. However, Python continues to be a useful tool for
automation of operations—the heart of typical DevOps work.
It is easy to learn and easy to write readable code is a necessity when a critical part of
the work is responding to a 4 a.m. alert and modifying some misbehaving program.
It has powerful bindings to C and C++, the universal languages of the operating
system—and yet is natively memory-safe, leading to few crashes at the automation layer.
Finally, although not true when it was created, Python is one of the most popular
languages. This means that it is relatively easy to hire people with Python experience and
easy to get training materials and courses for people who need to learn on the job.
This book guides you through how to take advantage of Python to automate
operations.
To get the most out of the book, you need to be somewhat familiar with Python. If
you are new to Python, there are many great resources to learn it, including the official
Python tutorial at docs.python.org. You also need to be somewhat familiar with Unix-like
operating systems like Linux, especially how to use the command line.
xvii
CHAPTER 1
Installing Python
Before you can use Python, you need to install it. Some operating systems, such as
macOS and some Linux variants, have Python preinstalled. Those versions of Python,
colloquially called system Python, often make poor defaults for people who want to
develop in Python.
The version of Python installed is often behind the latest practices. System
integrators often patch Python in ways that can lead to surprises. For example, Debian-
based Python is often missing modules like venv and ensurepip. macOS Python links
against a Mac shim around its native SSL library. Those things mean, especially when
starting and consuming FAQs and web resources, it is better to install Python from
scratch.
This chapter covers a few ways to do so and the pros and cons of each.
1.1 OS Packages
Volunteers have built ready-to-install packages for some of the more popular operating
systems.
The most famous is the deadsnakes PPA (Personal Package Archives). The dead in
the name refers to the fact that those packages are already built—with the metaphor
that sources are “alive.” Those packages are built for Ubuntu and usually support all the
versions of Ubuntu that are still supported upstream. Getting those packages is done
with a simple
1
© Moshe Zadka 2022
M. Zadka, DevOps in Python, https://doi.org/10.1007/978-1-4842-7996-0_1
Chapter 1 Installing Python
1.2 Using pyenv
pyenv tends to offer the highest return on investment for installing Python for local
development. The initial setup does have some subtleties. However, it allows installing
many side-by-side Python versions as needed. It also allows you to manage how each is
accessed—either using a per-user default or a per-directory default.
Installing pyenv itself depends on the operating system. On a macOS, the easiest
way is to install it via Homebrew. Note that in this case, pyenv itself might need to be
upgraded to install new versions of Python.
On a Unix-based operating system, such as Linux or FreeBSD, the easiest way to
install pyenv is by using the curl|bash command.
$ PROJECT=https://github.com/pyenv/pyenv-installer \
PATH=raw/master/bin/pyenv-installer \
curl -L $PROJECT/PATH | bash
Of course, this comes with its own security issues and could be replaced with a
two-step process where you can inspect the shell script before running or even use git-
checkout to pin to a specific revision.
2
Chapter 1 Installing Python
$ cd pyenv-installer
$ bash pyenv-installer
export PATH="~/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
or locally by using
Local means they are available in a given directory. This is done by putting a python-
version.txt file in this directory. This is important for version-controlled repositories,
but a few different strategies are used to manage those. One strategy is to add this file to
the ignored list. This is useful for heterogeneous teams or open source projects. Another
strategy is to check in the file so that the same version of Python is used in the repository.
Note that since pyenv is designed to install side-by-side versions of Python, it has no
concept of upgrading Python. A newer Python version needs to be installed with pyenv
and then set as the default.
By default, pyenv installs non-optimized versions of Python. If optimized versions
are needed, enter the following.
env PYTHON_CONFIGURE_OPTS="--enable-shared
--enable-optimizations
3
Chapter 1 Installing Python
--with-computed-gotos
--with-lto
--enable-ipv6" pyenv install
Let’s build a version that is pretty similar to binary versions from python.org.
4
Chapter 1 Installing Python
1.4 PyPy
The usual implementation of Python is sometimes known as CPython to distinguish
it from the language proper. The most popular alternative implementation is PyPy, a
Python-based JIT implementation of Python in Python. Because it has a dynamic JIT
(just-in-time) compilation to assembly, it can sometimes achieve phenomenal speed-
ups (three times or even ten times) over regular Python.
There are sometimes challenges in using PyPy. Many tools and packages are
tested only with CPython. However, sometimes spending the effort to check if PyPy is
compatible with the environment is worth it if performance matters.
There are a few subtleties in installing Python from source. While it is theoretically
possible to translate using CPython, in practice, the optimizations in PyPy mean that
translating using PyPy works on more reasonable machines. Even when installing from
source, it is better to first install a binary version to bootstrap.
The bootstrapping version should be PyPy, not PyPy3. PyPy is written in the
Python 2 dialect, which is one of the only cases where worrying about the deprecation
is irrelevant since PyPy is a Python 2 dialect interpreter. PyPy3 is the Python 3 dialect
implementation, which is usually better in production as most packages are slowly
dropping support for Python 2.
The latest PyPy3 supports 3.5 features of Python, as well as f-strings. However, the
latest async features, added in Python 3.6, do not work.
1.5 Anaconda
The closest to a system Python that is still reasonable for use as a development platform
is Anaconda, a metadistribution. It is, in essence, an operating system on top of the
operating system. Anaconda has its grounding in the scientific computing community,
and so its Python comes with easy-to-install modules for many scientific applications.
Many of these modules are non-trivial to install from PyPI, requiring a complicated build
environment.
It is possible to install multiple Anaconda environments on the same machine. This
is handy when needing different Python versions or different versions of PyPI modules.
To bootstrap Anaconda, you can use the bash installer available at https://conda.
io/miniconda.html. The installer also modifies ~/.bash_profile to add the path to
conda, the installer.
5
Chapter 1 Installing Python
conda environments are created using conda create --name <name> and activated
using source conda activate <name>. There is no easy way to use inactivated
environments. It is possible to create a conda environment while installing packages:
conda create --name some-name python. You can specify the version using = – conda
create --name some-name python=3.5. It is also possible to install more packages into
a conda environment, using conda install package[=version], after the environment
has been activated. Anaconda has a lot of prebuilt Python packages, especially ones
that are non-trivial to build locally. This makes it a good choice if those packages are
important to your use case.
1.6 Summary
Running a Python program requires an interpreter installed on the system. Depending
on the operating system and the versions, there are several different ways to install
Python. Using the system Python is a problematic option. On macOS and Unix systems,
using pyenv is almost always the preferred option. On Windows, using the prepackaged
installers from Python.org is often a good idea.
6
CHAPTER 2
Packaging
One of the main strengths of Python is the ecosystem, the third-party packages on
PyPI. There are packages to do anything from running computations in parallel on GPUs
for machine learning to reducing the boilerplate needed for writing classes. This means
that a lot of the practical work with Python is handling the third-party dependencies.
The current packaging tooling is pretty good, but things have not always been this
way. It is important to understand which best practices are antiquated rituals based on
faulty assumptions but have some merit and are actually good ideas.
When dealing with packaging, there are two ways to interact. One is to be a
consumer wanting to use the functionality of a package. Another is to be the producer,
publishing a package. These describe, usually, different development tasks, not
different people.
It is important to have a solid understanding of the consumer side of packages before
moving to production. If the goal of a package publisher is to be useful to the package
user, it is crucial to imagine the last mile before starting to write a single line of code.
2.1 Virtual Environments
Virtual environments are often misunderstood because the concept of environments is
not clear. A Python environment refers to the root of the Python installation. The reason
an environment is important is because of the lib/site-packages subdirectory of that
root. The lib/site-packages subdirectory is where third-party packages are installed.
The most popular tool to add packages to an environment is pip, which is covered
in the next section. Before using pip, it is important to understand how virtual
environments work.
A real environment is based on Python installation, which means that to get a new
real environment, a new Python must be installed and often rebuilt. This is sometimes
an expensive proposition.
7
© Moshe Zadka 2022
M. Zadka, DevOps in Python, https://doi.org/10.1007/978-1-4842-7996-0_2
Chapter 2 Packaging
The advantage of a virtual environment is that it is cheap to set up and tear down.
Some modern Python tooling takes advantage of that, setting up and tearing down
virtual environments as a normal part of their operation. Setting up and tearing down
virtual environments, being cheap and fast, is also a common part of Python developer
workflow.
A virtual environment copies the minimum necessary out of the real environment to
mislead Python into thinking it has a new root. The precise file structure is less important
than remembering that the command to create a virtual environment is simple and fast.
Here, simple means that all the command does is copy some files and perhaps make
a few symbolic links. Because of that, there are a few failure modes—mostly when file
creation fails because of permission issues or a full disk.
There are two ways to use virtual environments: activated and inactivated. To use
an inactivated virtual environment, which is most common in scripts and automated
procedures, you explicitly call Python from the virtual environment.
This means that a virtual environment in /home/name/venvs/my-special-env
calling /home/name/venvs/my-special-env/bin/python has a Python process that uses
this environment. For example, /home/name/venvs/my-special-env/bin/python -m
pip runs pip but installs in the virtual environment.
Note that entrypoint–based scripts are installed alongside Python, so running
/home/name/venvs/my-special-env/bin/pip also installs packages in the virtual
environment.
The other way to use a virtual environment is to activate it. Activating a virtual
environment in a bash-like shell means sourcing its activated script.
$ source /home/name/venvs/my-special-env/bin/activate
The sourcing sets a few environment variables, only one of which is important. The
important variable is PATH, which gets prefixed by /home/name/venvs/my-special-env/
bin. This means that commands like python or pip are found there first. Two cosmetic
variables are set. $VIRTUAL_ENV points to the root of the environment. This is useful
in management scripts that want to be aware of virtual environments. PS1 is prefixed
with (my-special-env), which is useful for visualizing the virtual environment while
working interactively in the console.
It is generally a good practice to only install third-party packages inside a virtual
environment. Combined with the fact that virtual environments are cheap, if one gets
into a bad state, it is best to remove the whole directory and start from scratch.
8
Chapter 2 Packaging
For example, imagine a bad package install that causes the Python start-up to fail.
Even running pip uninstall is impossible since pip fails on start-up. However, the
cheapness means you can remove the whole virtual environment and re-create it with a
good set of packages.
A modern practice is to move increasingly toward treating virtual environments as
semi-immutable. After creating them, there is a single stage for installing all required
packages. Instead of modifying the virtual environment if an upgrade is required, destroy
the environment, re-create, and reinstall.
The modern way to create virtual environments is to use the venv standard library
module. This only works on Python 3. Since Python 2 has been strongly deprecated since
the beginning of 2020, it is best avoided in any case.
venv is used as a command with python -m venv <directory>, as there is no
dedicated entrypoint. It creates the directory for the environment.
It is best if this directory does not exist before that. A best practice is to remove
it before creating the environment. There are also two options for creating the
environment: which interpreter to use and what initial packages to install.
2.2 pip
The packaging tool for Python is pip. There have been other tools that have mostly been
abandoned by the community and should not be used.
Installations of Python used to not come with pip out of the box. This has changed
in recent versions, but many versions which are still supported do not have it. When
running on such a version, python -m ensurepip installs it.
Some Python installations, especially system ones, disable ensurepip. When
lacking ensurepip, there is a way of manually getting it: get-pip.py. This is a single
downloadable file that, when executed, unpacks pip.
Luckily, pip is the only package that needs these weird gyrations to install. All other
packages can, and should, be installed using pip.
For example, if sample-environment is a virtual environment, installing the glom
package can be done with the following code.
The last command tests that glom has been properly installed. Glom is a package
to handle deeply-nested data, and called with no arguments, outputs an empty Python
dictionary. This makes it handy for quickly testing whether a new virtual environment
can install new packages properly.
Internally, pip is also treated as a third-party package. Upgrading pip itself is done
with pip install --upgrade pip.
Depending on how Python was installed, its real environment might or might not
be modifiable by the user. Many instructions in various README files and blogs might
encourage using sudo pip install. This is almost always the wrong thing to do; it
installs the packages in the global environment.
The pip install command downloads and installs all dependencies. However,
it can fail to downgrade incompatible packages. It is always possible to install explicit
versions: pip install package-name==<version> installs this precise version. This is
also a good way for local testing to get explicitly non-general-availability packages, such
as release candidates, beta, or similar.
If wheel is installed, pip builds, and usually caches, wheels for packages. This is
especially useful when dealing with a high virtual environment churn since installing a
cached wheel is a fast operation. This is also highly useful when dealing with native or
binary packages that need to be compiled with a C compiler. A wheel cache eliminates
the need to build it again.
pip does allow uninstalling with pip uninstall <package>. This command, by
default, requires manual confirmation. Except for exotic circumstances, this command
is not used. If an unintended package has snuck in, the usual response is to destroy the
environment and rebuild it. For similar reasons, pip install --upgrade <package>
is not often needed; the common response is to destroy and re-create the environment.
There is one situation where it is a good idea.
pip install supports a requirements file: pip install --requirements or pip
install -r. The requirements file simply has one package per line. This is no different
from specifying packages on the command line. However, requirement files often specify
strict dependencies. A requirements file can be generated from an environment with
pip freeze.
Like most individual packages or wheels, installing anything that is not strict and
closed under requirements requires pip to decide which dependencies to install. The
general problem of dependency resolution does not have an efficient and complete
solution. Different strategies are possible to approach such a solution.
10
Chapter 2 Packaging
The way pip resolves dependencies is by using backtracking. This means that
it optimistically tries to download the latest possible requirements recursively. If a
dependency conflict is found, it backtracks; try a different option.
As an example, consider three packages.
• top
• middle
• base
There are two base versions: 1.0 and 2.0. The package dependencies are setup.
cfg files.
The following is for the top.
[metadata]
name = top
version = 1.0
[options]
install_requires =
base
middle
[metadata]
name = middle
version = 1.0
[options]
install_requires =
base<2.0
The base package has two versions: 1.0 and 2.0. It does not have any dependencies.
Because top depends directly on base, pre-backtracking versions of pip get the latest
and then have a failed resolution.
11
Chapter 2 Packaging
This solution has the advantage that it is complete, but it can take unfeasible amounts
of time in certain cases. This is rare, but merely taking a long time is not.
One way to increase the speed is to include >= dependencies in the loose
requirements. This is usually a good idea since packages are better at guaranteeing
backward compatibility than forward compatibility. As a side benefit, this can
dramatically reduce the solution space that pip needs to backtrack in.
In most scenarios, it is better to use strict requirements for day-to-day development
and regenerate the strict requirements from the loose requirements (which can take a
while) on a cadence that balances keeping up to date with churn.
12
Chapter 2 Packaging
together. The pedantic way to call installable things is distribution. A distribution can
correspond to no packages (it can be a top-level single-module distribution) or multiple
packages.
It is good to keep a 1-1-1 relationship when packaging things: a single distribution
corresponding to one package and named the same. Even if there is only one file, put it
as an __init__.py file under a directory.
Packaging is an area that has seen a lot of changes. Copying and pasting from
existing packages is not a good idea; good packages are, for the most part, mature
packages. Following the latest best practices means making changes to an existing
working process.
Starting with setuptools version 61.0.0, it is possible to create a package with only
two files besides the code files.
• pyproject.toml
• README.rst
The README is not strictly necessary. However, most source code management
systems display it rendered, so it is best to break it out into its own file.
Even an empty pyproject.toml generates a package. However, almost all packages
need at least a few more details.
The build-system is the one mandatory section in a non-empty pyproject.toml file.
It is usually the first.
[build-system]
requires = [
"setuptools"
]
build-backend = "setuptools.build_meta"
Many systems can be used to build valid distributions. The setuptools system,
which used to be the only possibility, is now one of several. However, it is still the most
popular one.
Most of the rest of the data can be found in the project section.
[project]
name = "awesome_package"
version = "0.0.3"
description = "A pretty awesome package"
13
Chapter 2 Packaging
readme = "README.rst"
authors = [{name = "My Name",
email = "[email protected]"}]
dependencies = ["httpx"]
For most popular code organizations, this is enough for the setuptools systems to
find the code and create a correct package.
There are ways to have setuptools treat the version as dynamic and take it from a
file or an attribute. An alternative is to take advantage of pyproject.toml in a structured
format and manipulate it directly.
For example, the following code uses a CalVer (calendar versioning) scheme of
YEAR.MONTH.release in a month. It uses the built-in zoneinfo module, which requires
Python 3.9 or above, and the tomlkit library, which supports roundtrip-preserving TOML
parsing and serialization.
import tomlkit
import datetime
import os
import pathlib
import zoneinfo
now = datetime.datetime.now(tz=zoneinfo.ZoneInfo("UTC"))
prefix=f"{now.year}.{now.month}."
pyproject = pathlib.Path("pyproject.toml")
data = tomlkit.loads(pyproject.read_text())
current = data["project"].get("version", "")
if current.startswith(prefix):
serial = int(current.split(".")[-1]) + 1
else:
serial = 0
version = prefix + str(serial)
data["project"]["version"] = version
pyproject.write_text(tomlkit.dumps(data))
Some utilities keep the version synchronized between several files; for example,
pyproject.toml and example_package/__init__.py. The best way to use these utilities
is by not needing to do it.
14
Chapter 2 Packaging
# example_package/__init__.py
from importlib import metada
__version__ = metadata.distribution("example_package").version
del metadata # Keep top-level namespace clean
[project.scripts]
example-command = "example_package.commands:main"
# example_package/commands.py
def main():
print("an example")
$ example-command
an example
15
Chapter 2 Packaging
You can build a distribution with pyproject.toml, a README.rst, and some Python
code. There are several formats a distribution can take, but the one covered here is
the wheel.
After installing build using pip install build, run
This creates a wheel under dist. If the wheel needs to be in a different directory,
add --outdir <output directory> to the command.
You can do several things with the wheel, but it is important to note that one thing
you can do is pip install <wheel file>. Doing this as part of continuous integration
makes sure the wheel, as built by the current directory, is functional.
It is possible to use python -m build to create a source distribution. This is usually a
good idea to accommodate use cases that prefer to install from source. These use cases
are esoteric, but generating the source distribution is easy enough to be worth it.
It is possible to combine the --sdist and --wheel arguments into one run of
python -m build. This is also what python -m build does by default: create both a
source distribution and a wheel.
By default, python -m build installs any packages it needs to build the package in
a fresh virtual environment. When running python -m build in a tight edit-debug loop,
perhaps to debug a setup.cfg, this can get tedious. In those cases, create and activate a
virtual environment, and then run
This installs its dependencies in the current environment. While this is not a good fit
for production use, this is a faster way to debug packaging issues.
2.4 Binary Wheels
Python is well known and often used as an integration language. One of the ways this
integration happens is by linking to native code.
This is usually done using the C Application Binary Interface (C ABI). The C ABI is
used not only for integrating with C libraries but with other languages, such as C++, Rust,
or Swift, which can generate C ABI-compatible interfaces.
16
Chapter 2 Packaging
There needs to be some glue code bridging the C ABI to Python to integrate Python
with such code. It is possible to write this code by hand.
This is a tedious and error-prone process, so code generators are often used. Cython
is a popular generator that uses a Python-compatible language. Although Cython is often
used to interface to C ABI libraries, it can be used to generate extensions without such
integration. This makes examples slightly simpler, so the following Cython code is used
as a running example.
#cython: language_level=3
This code is in the binary_module.pyx file. It is short and does just enough to be
clear if it works correctly.
To build code with native integration, the files that describe the build are slightly
more complicated.
The pyproject.toml file is no longer empty. It now has two lines.
[build-system]
requires = ["setuptools", "cython"]
This makes sure the cython package is installed before trying to build a wheel.
The setup.py is no longer minimal. It contains enough code to integrate
with Cython.
import setuptools
from Cython import Build
setuptools.setup(
ext_modules=Build.cythonize("binary_module.pyx"),
)
17
Another Random Scribd Document
with Unrelated Content
many cases. Filthy?—yes. Savage or dangerous?—not at all. I
noticed the large number of cheap cloth caps worn by the men and
boys and the large number of dull gray shawls wrapped slatternwise
about the shoulders of the women. This world looked sad enough in
all conscience, inexpressibly so, but because of the individual houses
in many instances, the clean streets and the dark tiny shops, not
unendurable—even homey in instances. I ventured to ask a stalwart
London policeman—they are all stalwart in London—“Where are the
very poor in the East End—the poorest there are?”
“Well, most of these people hereabouts have little enough to live
on,” he observed, looking straight before him with that charming
soldierly air the London policemen have—his black strap under his
chin.
I walked long distances through such streets as Old Montague,
King Edward, Great Carden, Hope, Brick Lane, Salesworthy, Flower,
Dean, Hare, Fuller, Church Row, Cheshire, Hereford,—a long, long
list, too long to give here, coming out finally at St. John’s Catholic
Church at Bethnal Green and taking a car line for streets still farther
out. I had studied shops, doorways, areas, windows, with constant
curiosity. The only variation I saw to a dead level of sameness,
unbroken by trees, green places or handsome buildings of any kind,
were factory chimneys and endless charitable institutions covering,
apparently, every form of human weakness or deficiency, but looking
as if they were much drearier than the thing they were attempting
to cure. One of them I remember was an institution for the orphans
of seamen, and another a hospital for sick Spanish Jews. The
lodging-houses for working-girls and working-boys were so
numerous as to be discouraging and so dreary looking that I
marveled that any boy or girl should endure to live in them. One
could sense all forms of abuse and distress here. It would spring
naturally out of so low a grade of intelligence. Only a Dickens,
guided by the lamp of genius, could get at the inward spirit of these,
and then perhaps it would not avail. Life, in its farthest reaches,
sinks to a sad ugly mess and stays there.
One of the places that I came upon in my perambulations was a
public washhouse, laundry and bath, established by the London
County Council, if I remember rightly, and this interested me greatly.
It was near Winchester Street and looked not unlike a low, one-
story, factory building. Since these things are always fair indications
of neighborhoods, I entered and asked permission to inspect it. I
was directed to the home or apartment of a small martinet of a
director or manager, quite spare and dark and cockney, who frowned
on me quizzically when he opened his door,—a perfect devil of a
cheap superior who was for putting me down with a black look. I
could see that it was one of the natives he was expecting to
encounter.
“I would like to look over the laundry and baths,” I said.
“Where do you come from?” he asked.
“America,” I replied.
“Oh! Have you a card?”
I gave him one. He examined it as though by some chance it
might reveal something concerning me. Then he said if I would go
round to the other side he would admit me. I went and waited a
considerable time before he appeared. When he did, it was to lead
me with a very uncertain air first into the room filled with homely
bath closets, where you were charged a penny more or less—
according to whether you had soap and towel or not—and where the
tubs were dreary affairs with damp-looking wooden tops or flanges,
and thence into the washroom and laundry-room, where at this time
in the afternoon—about four o’clock—perhaps a score of women of
the neighborhood were either washing or ironing.
Dreary! dreary! dreary! Ghastly! In Italy, later, and southern
France, I saw public washing under the sky, beside a stream or near
a fountain—a broken, picturesque, deliciously archaic fountain in one
instance. Here under gray skies, in a gray neighborhood, and in this
prison-like washroom was one of the most doleful pictures of life the
mind of man could imagine. Always when I think of the English, I
want to go off into some long analysis of their character. We have so
much to learn of life, it seems to me, and among the first things is
the chemistry of the human body. I always marvel at the nature of
the fluids which make up some people. Different climates must
produce different kinds, just as they produce strange kinds of trees
and animals. Here in England this damp, gray climate produces a
muggy sort of soul which you find au naturel only when you walk
among the very poor in such a neighborhood as this. Here in this
wash-house I saw the low English au naturel, but no passing
commentary such as this could do them justice. One would have to
write a book in order to present the fine differences. Weakness,
lowness of spirit, a vague comprehension of only the simplest things,
combined with a certain meaty solidarity, gave me the creeps. Here
they were, scrubbing or ironing; strings tied around their
protuberant stomachs to keep their skirts up; clothes the color of
lead or darker, and about as cheerful; hair gray or brownish-black,
thin, unkempt; all of them flabby and weary-looking—about the
atmosphere one would find in an American poorhouse.
They washed here because there were no washing facilities in
their own homes—no stationary tubs, no hot or cold water, no
suitable stoves to boil water on. It was equally true of ironing
facilities, the director told me. They came from blocks away. Some
women washed here for whole vicinities—the more industrious ones.
And yet few came here at that—the more self-respecting stayed
away. I learned this after a long conversation with my guide whose
principal commentary was that they were a worthless lot and that
you had to watch them all the time. “If you don’t,” he said in
cockney English, “they won’t keep things clean. You can’t teach ’em
scarcely how to do things right. Now and then they gets their hands
caught.” He was referring to the washing-drums and the mangles. It
was a long story, but all I got out of it was that this was a dreary
world, that he was sick of his position but compelled to keep it for
financial reasons, that he wanted as little as possible to do with the
kind of cattle which he considered these people to be and that he
would prefer to give it up. There was a touch of socialism in all this
—trying to do for the masses—but I argued that perhaps under
more general socialistic conditions things would be better; certainly,
one would have to secure more considerate feelings on the part of
directors and some public approval which would bring out the better
elements. Perhaps under truer socialism, however, public wash-
houses would not be necessary at all. Anyhow, the cry from here to
Bond Street and the Houses of Parliament and the stately world of
the Lords seemed infinitely far. What can society do with the sad,
shadowy base on which it rests?
I came another day to another section of this world, approaching
the East End via Aldgate and Commercial Road, and cutting through
to Bethnal Green via Stepney. I found the same conditions—clean
streets, low gray buildings, shabby people, a large museum whose
chief distinction was that the floor of its central rotunda had been
laid by women convicts!—and towering chimneys. So little life
existed in the streets, generally speaking, that I confess I was
depressed. London is so far flung. There were a great many Jews of
Russian, Roumanian and Slavic extraction, nearly all bearing the
marks of poverty and ignorance, but looking shrewd enough at that,
and a great many physically deteriorated English. The long-bearded
Jew with trousers sagging about his big feet, his small derby hat
pulled low over his ears, his hands folded tightly across his back,
was as much in evidence here as on the East Side in New York. I
looked in vain for restaurants or show places of any kind (saloons,
moving pictures, etc.). There were scarcely any here. This whole
vicinity seemed to me to be given up to the poorest kind of living—
sad, drab, gray. No wonder the policeman said to me: “Most of these
people hereabouts have little enough to live on.” I’m sure of it.
Finally, after a third visit, I consulted with another writer, a reputed
authority on the East End, who gave me a list of particular
neighborhoods to look at. If anything exceptional was to be detected
from the appearance of the people, beyond what I have noted, I
could not see it. I found no poor East End costers with buttons all
over their clothes, although they once existed here. I found no
evidence of the overcrowded home life, because I could not get into
the houses to see. Children, it seemed to me, were not nearly so
numerous as in similar areas in American cities. Even a police-court
proceeding I saw in Avon Square was too dull to be interesting. I
was told I might expect the most startling crimes. The two hours I
spent in court developed only drunkenness and adultery. But as my
English literary guide informed me, only time and familiarity with a
given neighborhood would develop anything. I believe this. All I felt
was that in such a dull, sordid, poor-bodied world any depth of filth
or crime might be reached, but who cares to know?
CHAPTER XV
ENTER SIR SCORP
D
URING all my stay at Bridgely Level I had been hearing
more or less—an occasional remark—of a certain Sir
Scorp, an Irish knight and art critic, a gentleman who had
some of the finest Manets in the world. He had given
Dublin its only significant collection of modern pictures—in fact,
Ireland should be substituted for Dublin, and for this he was
knighted. He was the art representative of some great museum in
South Africa—at Johannesburg, I think,—and he was generally
looked upon as an authority in the matter of pictures.
T
HE Christmas holidays were drawing near and Barfleur was
making due preparations for the celebration of that event.
He was a stickler for the proper observance of those things
which have national significance and national or
international feeling behind them. Whatever joy he might get out of
such things, much or little, I am convinced that he was much more
concerned lest some one should fail of an appropriate share of
happiness than he was about anything else. I liked that in Barfleur. It
touched me greatly, and made me feel at times as though I should
like to pat him on the head.
I was all agog. The picture she had presented was so smart.
Barfleur was interested though perhaps disappointed, too, that
Gerard knew her when he didn’t.
“This is most fortunate,” he said to me solemnly. “Now if it
should turn out that he does know her, we can call there Christmas
day after dinner. Or perhaps he will take you.”
This came a little regretfully, I think, for Gerard Barfleur
accounted himself an equal master with his cousin in the matter of
the ladies, and was not to be easily set aside. So Christmas eve it
was decided that Gerard should, on the morrow, reconnoiter the
Churchill country house early, and report progress, while we went to
church. Fancy Barfleur and me marching to church Christmas
morning with the children!
Christmas in England! The day broke clear and bright, and there
we all were. It was not cold, and as is usual, there was little if any
wind. I remember looking out of my window down into the valley
toward Bridgely, and admiring the green rime upon the trees, the
clustered chimneys of a group of farmers’ and working-men’s
cottages, the low sagging roofs of red tile or thatch, and the small
window panes that always somehow suggest a homey simplicity that
I can scarcely resist. The English milkmaid of fiction, the simple
cottages, the ordered hierarchy of farmers are, willy nilly, fixtures in
my mind. I cannot get them out.
First then, came a breakfast in our best bibs and tuckers, for
were we not to depart immediately afterwards to hear an English
Christmas service? Imagine Barfleur—the pride of Piccadilly,—
marching solemnly off at the head of his family to an old, gray abbey
church. As the French say, “I smile.” We all sat around and had our
heavy English breakfast,—tea, and, to my comfort and delight, “Mr.
Jones’s sausages.” Barfleur had secured a string of them from
somewhere.
“Think of it,” commented Berenice sardonically. “‘Mr. Jones’s
sausages’ for breakfast. Aren’t they comic! Do you like them?”
“I most assuredly do.”
“And do you eat them every day in A-máy-reeka?” queried
Charles Gerard with a touch of latent jesting in his voice.
“When I can afford them, yes.”
“They’re quite small, aren’t they?” commented five-year-old
James Herbert.
“Precisely,” I replied, unabashed by this fire of inquiry. “That’s
their charm.”
The church that we visited was one of those semi-ancient abbey
affairs, done in good English Gothic, with a touch of Tudor here and
there, and was located outside the village of Bridgely Level two or
three miles from Barfleur’s home. I recall with simple pleasure the
smug, self-righteous, Sunday-go-to-meeting air with which we all set
forth, crossing homey fields via diagonal paths, passing through
stiles and along streams and country roads, by demure little cottages
that left one breathless with delight. I wish truly that England could
be put under glass and retained as a perfect specimen of
unconscious, rural poetry—the south of England. The pots and pans
outside the kitchen doorways! The simple stoop, ornamented with
clambering vines! The reddish-green sagging roofs with their
clustered cylindrical chimneypots! When we came to the top of a hill
we could see the church in the valley below, nestling beside one
bank of the Thames which wound here and there in delightful S’s. A
square tower, as I recall, rose quaintly out of a surrounding square
of trees, grass, grave-stones and box-hedge.
There was much ado in this semi-ancient place as we came up,
for Christmas day, of all days, naturally drew forth a history-loving
English audience. Choir boys were scurrying here and there, some
ladies of solemn demeanor, who looked as if they might be assisting
at the service in some way or another, were dawdling about, and I
even saw the rector in full canonicals hastening up a gravel path
toward a side door, as though matters needed to be expedited
considerably. The interior was dark, heavy-beamed, and by no
means richly ornamented with stained glass, but redolent of by-gone
generations at that. The walls were studded with those customary
slabs and memorial carvings with which the English love to
ornament their church interiors. A fair-sized, and yet for so large an
edifice, meager audience was present, an evidence it seemed to me,
of the validity of the protest against state support for the Established
Church. There was a great storm of protest in England at this time
against the further state support of an institution that was not
answering the religious needs of the people, and there had been
some discussion of the matter at Barfleur’s house. As was natural,
the artistically inclined were in favor of anything which would
sustain, unimpaired, whether they had religious value or not, all the
old cathedrals, abbeys, and neighborhood churches, solely because
of their poetic appearance. On the other hand an immense class,
derisively spoken of as “chapel people,” were heartily in favor of the
ruder disposition of the matter. Barfleur in his best Piccadilly clothing
was for their maintenance.
To be frank, as charming as was this semi-ancient atmosphere,
and possibly suited to the current English neighborhood mood (I
could not say as to that), it did not appeal to me as strongly on this
occasion as did many a similar service in American churches of the
same size. The vestments were pleasing as high church vestments
go; the choir, made of boys and men from the surrounding
countryside no doubt, was not absolutely villainous but it could have
been much better. To tell the truth, it seemed to me that I was
witnessing the last and rather threadbare evidences of an older and
much more prosperous order of things. Beautiful in its way? Yes.
Quaint? Yes. But smacking more of poverty and an ordered system
continued past its day than anything else. I felt a little sorry for the
old church and the thin rector and the goodly citizens, albeit a little
provincial, who clung so fatuously to a time-worn form. They have
their place, no doubt, and it makes that sweet, old lavender
atmosphere which seems to hover over so much that one