Python Debugging For Ai Machine Learning and Cloud Computing A Pattern Oriented Approach 1St Edition Vostokov All Chapter

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 68

Python Debugging for AI, Machine

Learning, and Cloud Computing: A


Pattern-Oriented Approach 1st Edition
Vostokov
Visit to download the full and correct content document:
https://ebookmass.com/product/python-debugging-for-ai-machine-learning-and-cloud-
computing-a-pattern-oriented-approach-1st-edition-vostokov/
Dmitry Vostokov

Python Debugging for AI, Machine


Learning, and Cloud Computing
A Pattern-Oriented Approach
Dmitry Vostokov
Dalkey, Dublin, Ireland

ISBN 978-1-4842-9744-5 e-ISBN 978-1-4842-9745-2


https://doi.org/10.1007/978-1-4842-9745-2

© Dmitry Vostokov 2024

Apress Standard

The use of general descriptive names, registered names, trademarks,


service marks, etc. in this publication does not imply, even in the
absence of a specific statement, that such names are exempt from the
relevant protective laws and regulations and therefore free for general
use.

The publisher, the authors, and the editors are safe to assume that the
advice and information in this book are believed to be true and accurate
at the date of publication. Neither the publisher nor the authors or the
editors give a warranty, expressed or implied, with respect to the
material contained herein or for any errors or omissions that may have
been made. The publisher remains neutral with regard to jurisdictional
claims in published maps and institutional affiliations.

This Apress imprint is published by the registered company APress


Media, LLC, part of Springer Nature.
The registered company address is: 1 New York Plaza, New York, NY
10004, U.S.A.
To Ekaterina, Alexandra, Kirill, and Maria
Introduction
Python is the dominant language used in AI and machine learning with
data and pipelines in cloud environments. Besides debugging Python
code in popular IDEs, notebooks, and command-line debuggers, this
book also includes coverage of native OS interfacing (Windows and
Linux) necessary to understand, diagnose, and debug complex software
issues.
The book begins with an introduction to pattern-oriented software
diagnostics and debugging processes that, before doing Python
debugging, diagnose problems in various software artifacts such as
memory dumps, traces, and logs. Next, it teaches various debugging
patterns using Python case studies that model abnormal software
behavior. Further, it covers Python debugging specifics in cloud native
and machine learning environments. It concludes with how recent
advances in AI/ML can help in Python debugging. The book also goes
deep for case studies when there are environmental problems, crashes,
hangs, resource spikes, leaks, and performance degradation. It includes
tracing and logging besides memory dumps and their analysis using
native WinDbg and GDB debuggers.
This book is for those who wish to understand how Python
debugging is and can be used to develop robust and reliable AI,
machine learning, and cloud computing software. It uses a novel
pattern-oriented approach to diagnosing and debugging abnormal
software structure and behavior. Software developers, AI/ML
engineers, researchers, data engineers, MLOps, DevOps, and anyone
who uses Python will benefit from this book.
Source Code: All source code used in this book can be downloaded
from github.com/Apress/Python-Debugging-for-AI-
Machine-Learning-and-Cloud-Computing.
Any source code or other supplementary material referenced by the
author in this book is available to readers on GitHub. For more detailed
information, please visit https://www.apress.com/gp/services/source-
code.
Table of Contents
Chapter 1:​Fundamental Vocabulary
Process
Thread
Stack Trace (Backtrace, Traceback)
Symbol Files
Module
Memory Dump
Crash
Hang
Summary
Chapter 2:​Pattern-Oriented Debugging
The History of the Idea
Patterns and Analysis Patterns
Development Process
Development Patterns
Debugging Process and Patterns
Elementary Diagnostics Patterns
Debugging Analysis Patterns
Debugging Architecture Patterns
Debugging Design Patterns
Debugging Implementation Patterns
Debugging Usage Patterns
Debugging Presentation Patterns
Summary
Chapter 3:​Elementary Diagnostics Patterns
Functional Patterns
Use-Case Deviation
Non-Functional Patterns
Crash
Hang
Counter Value
Error Message
Summary
Chapter 4:​Debugging Analysis Patterns
Paratext
State Dump
Counter Value
Stack Trace Patterns
Stack Trace
Runtime Thread
Managed Stack Trace
Source Stack Trace
Stack Trace Collection
Stack Trace Set
Exception Patterns
Managed Code Exception
Nested Exception
Exception Stack Trace
Software Exception
Module Patterns
Module Collection
Not My Version
Exception Module
Origin Module
Thread Patterns
Spiking Thread
Active Thread
Blocked Thread
Blocking Module
Synchronization Patterns
Wait Chain
Deadlock
Livelock
Memory Consumption Patterns
Memory Leak
Handle Leak
Case Study
Summary
Chapter 5:​Debugging Implementation Patterns
Overview of Patterns
Break-Ins
Code Breakpoint
Code Trace
Scope
Variable Value
Type Structure
Breakpoint Action
Usage Trace
Case Study
Elementary Diagnostics Patterns
Debugging Analysis Patterns
Debugging Implementation Patterns
Summary
Chapter 6:​IDE Debugging in the Cloud
Visual Studio Code
WSL Setup
Cloud SSH Setup
Case Study
Summary
Chapter 7:​Debugging Presentation Patterns
Python Debugging Engines
Case Study
Suggested Presentation Patterns
Summary
Chapter 8:​Debugging Architecture Patterns
The Where?​Category
In Papyro
In Vivo
In Vitro
In Silico
In Situ
Ex Situ
The When?​Category
Live
JIT
Postmortem
The What?​Category
Code
Data
Interaction
The How?​Category
Software Narrative
Software State
Summary
Chapter 9:​Debugging Design Patterns
CI Build Case Study
Elementary Diagnostics
Analysis
Architecture
Design
Implementation
Data Processing Case Study
Elementary Diagnostics
Analysis
Architecture
Design
Implementation
Summary
Chapter 10:​Debugging Usage Patterns
Exact Sequence
Scripting
Debugger Extension
Abstract Command
Space Translation
Lifting
Gestures
Summary
Chapter 11:​Case Study:​Resource Leaks
Elementary Diagnostics
Debugging Analysis
Debugging Architecture
Debugging Implementation
Summary
Chapter 12:​Case Study:​Deadlock
Elementary Diagnostics
Debugging Analysis
Debugging Architecture
Exceptions and Deadlocks
Summary
Chapter 13:​Challenges of Python Debugging in Cloud Computing
Complex Distributed Systems
Granularity of Services
Communication Channels Overhead
Inter-Service Dependencies
Layers of Abstraction
Opaque Managed Services
Serverless and Function as a Service
Container Orchestration Platforms
Continuous Integration/​Continuous Deployment
Pipeline Failures
Rollbacks and Versioning
Immutable Infrastructure
Diversity of Cloud Service Models
Infrastructure as a Service
Platform as a Service
Software as a Service
Evolving Cloud Platforms
Adapting to Changes
Staying Updated
Environment Parity
Library and Dependency Disparities
Configuration Differences
Underlying Infrastructure Differences
Service Variabilities
Limited Visibility
Transient Resources
Log Management
Monitoring and Alerting
Latency and Network Issues
Network Instabilities
Service-to-Service Communication
Resource Leaks and Performance
Resource Starvation
Concurrency Issues
Race Conditions
Deadlocks
Security and Confidentiality
Debugger Access Control Restrictions
Sensitive Data Exposure
Limited Access
Cost Implications
Extended Sessions
Resource Provisioning and Deprovisioning
Data Transfer and Storage Fees
State Management
Stateful Services
Data Volume
Limited Tooling Compatibility
Versioning Issues
Deprecations and Changes
SDK and Library Updates
Real-time Debugging and User Experience
External Service Dependencies
Dependency Failures
Rate Limiting and Quotas
Asynchronous Operations
Flow Tracking
Error Propagation
Scaling and Load Challenges
Load-Based Issues
Resource Contention
Multi-Tenancy Issues
Resource Contention
Data Security
Reliability and Redundancy Issues
Service Failures
Data Durability
Summary
Chapter 14:​Challenges of Python Debugging in AI and Machine
Learning
The Nature of Defects in AI/​ML
Complexity and Abstraction Layers
Non-Determinism and Reproducibility
Large Datasets
High-Dimensional Data
Long Training Times
Real-Time Operation
Model Interpretability​
Hardware Challenges
Version Compatibility and Dependency Hell
Data Defects
Inconsistent and Noisy Data
Data Leakage
Imbalanced Data
Data Quality
Feature Engineering Flaws
Algorithmic and Model-Specific Defects
Gradients, Backpropagation, and Automatic Differentiation
Hyperparameter Tuning
Overfitting and Underfitting
Algorithm Choice
Deep Learning Defects
Activation and Loss Choices
Learning Rate
Implementation Defects
Tensor Shapes
Hardware Limitations and Memory
Custom Code
Performance Bottlenecks
Testing and Validation
Unit Testing
Model Validation
Cross-Validation
Metrics Monitoring
Visualization for Debugging
TensorBoard
Matplotlib and Seaborn
Model Interpretability​
Logging and Monitoring
Checkpoints
Logging
Alerts
Error Tracking Platforms
Collaborative Debugging
Forums and Communities
Peer Review
Documentation, Continuous Learning, and Updates
Maintaining Documentation
Library Updates
Continuous Learning
Case Study
Summary
Chapter 15:​What AI and Machine Learning Can Do for Python
Debugging
Automated Error Detection
Intelligent Code Fix Suggestions
Interaction Through Natural Language Queries
Visual Debugging Insights
Diagnostics and Anomaly Detection
Augmenting Code Reviews
Historical Information Analysis and Prognostics
Adaptive Learning and Personalized Debugging Experience
Test Suite Integration and Optimization
Enhanced Documentation and Resource Suggestions
Problem Modeling
Generative Debugging Strategy
Help with In Papyro Debugging
Summary
Chapter 16:​The List of Debugging Patterns
Elementary Diagnostics Patterns
Debugging Analysis Patterns
Debugging Architecture Patterns
Debugging Design Patterns
Debugging Implementation Patterns
Debugging Usage Patterns
Debugging Presentation Patterns
Index
About the Author
Dmitry Vostokov
is an internationally recognized expert,
speaker, educator, scientist, inventor, and
author. He founded the pattern-oriented
software diagnostics, forensics, and
prognostics discipline (Systematic
Software Diagnostics) and Software
Diagnostics Institute (DA+TA:
DumpAnalysis.org + TraceAnalysis.org).
Vostokov has also authored multiple
books on software diagnostics, anomaly
detection and analysis, software, and
memory forensics, root cause analysis
and problem-solving, memory dump
analysis, debugging, software trace and log analysis, reverse
engineering, and malware analysis. He has over thirty years of
experience in software architecture, design, development, and
maintenance in various industries, including leadership, technical, and
people management roles. In his spare time, he presents multiple topics
on Debugging.TV and explores software narratology and its further
development as narratology of things and diagnostics of things (DoT),
software pathology, and quantum software diagnostics. His current
interest areas are theoretical software diagnostics and its mathematical
and computer science foundations, application of formal logic, artificial
intelligence, machine learning, and data mining to diagnostics and
anomaly detection, software diagnostics engineering and diagnostics-
driven development, diagnostics workflow, and interaction. Recent
interest areas also include cloud native computing, security,
automation, functional programming, applications of category theory to
software development and big data, and artificial intelligence
diagnostics.
About the Technical Reviewer
Krishnendu Dasgupta
is currently the Head of Machine
Learning at Mondosano GmbH, leading
data science initiatives focused on
clinical trial recommendations and
advanced patient health profiling
through disease and drug data. Prior to
this role, he co-founded DOCONVID AI, a
startup that leveraged applied AI and
medical imaging to detect lung
abnormalities and neurological
disorders.
With a strong background in
computer science engineering,
Krishnendu has more than a decade of experience in developing
solutions and platforms using applied machine learning. His
professional trajectory includes key positions at prestigious
organizations such as NTT DATA, PwC, and Thoucentric.
Krishnendu’s primary research interests include applied AI for
graph machine learning, medical imaging, and decentralized privacy-
preserving machine learning in healthcare. He also had the opportunity
to participate in the esteemed Entrepreneurship and Innovation
Bootcamp at the Massachusetts Institute of Technology, cohort of 2018
batch.
Beyond his professional endeavors, Krishnendu actively dedicates
his time to research, collaborating with various research NGOs and
universities worldwide. His focus is on applied AI and ML.
© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2024
D. Vostokov, Python Debugging for AI, Machine Learning, and Cloud Computing
https://doi.org/10.1007/978-1-4842-9745-2_1

1. Fundamental Vocabulary
Dmitry Vostokov1

(1) Dalkey, Dublin, Ireland

Debugging complex software issues in machine learning and cloud computing


environments requires not only the knowledge of the Python language and its interpreter
(or compiler), plus standard and external libraries, but also necessary and relevant
execution environment and operating system internals. In this chapter, you will review
some necessary fundamentals from software diagnostics and debugging languages to
have the same base level of understanding for the following chapters. In this book, I
assume that you are familiar with the Python language and its runtime environment.

Process
A Python script is interpreted by compiling it into bytecode and then executing it, or it
can even be precompiled into an application program. In both cases, this interpreter file
or the compiled application is an executable program (in Windows, it may have a .exe
extension) that references some operating system libraries (.dll in Windows and .so in
Linux). This application can be loaded into computer memory several times; each time, a
separate process is created with its own resources and unique process ID (PID, also
TGID), as shown in Figure 1-1. The process may also have a parent process that created it,
with a parent process ID (PPID).
Figure 1-1 Two python3 processes with two different PIDs
To illustrate, I executed the code in Listing 1-1 on both Windows and Linux twice.

import time

def main():
foo()

def foo():
bar()

def bar():
while True:
time.sleep(1)

if __name__ == "__main__":
main()
Listing 1-1 A Simple Script to Model Running Python Code

Figure 1-2 shows two processes on Windows.


Figure 1-2 Two running python3.11.exe processes on Windows
On Linux, you can also see two processes when you execute the same script in two
separate terminals:

~/Chapter1$ which python3


/usr/bin/python3

~/Chapter1$ ps -a
PID TTY TIME CMD
17 pts/0 00:00:00 mc
60 pts/2 00:00:00 python3
61 pts/1 00:00:00 python3
80 pts/3 00:00:00 ps

Note The operating system controls hardware and processes/threads. From a high
level, it is just a collection of processes with the operating system kernel as a process
too.

Thread
From an operating system perspective, a process is just a memory container for a Python
interpreter, its code, and data. But the interpreter code needs to be executed, for example,
to interpret the Python bytecode. This unit of execution is called a thread. A process may
have several such units of execution (several threads, the so-called multithreaded
application). Each thread has its own unique thread ID (TID, also LWP or SPID), as shown
in Figure 1-3. For example, one thread may process user interface events and others may
do complex calculations in response to UI requests, thus making the UI responsive. On
Windows, thread IDs are usually different from process IDs, but in Linux, the thread ID of
the main thread is the same as the process ID for a single-threaded process.

Figure 1-3 Two python3 processes with different numbers of threads


To model multithreading, I executed the code in Listing 1-2 on both Windows and
Linux.

import time
import threading

def thread_func():
foo()

def main():
t1 = threading.Thread(target=thread_func)
t1.start()
t2 = threading.Thread(target=thread_func)
t2.start()
t1.join()
t2.join()
def foo():
bar()

def bar():
while True:
time.sleep(1)

if __name__ == "__main__":
main()
Listing 1-2 A Simple Script to Model Multiple Threads
Figure 1-4 shows that in Windows, you can see 11 threads at the beginning (this
number later changes to 7 and then to 5). You see that the number of threads may be
greater than expected.

Figure 1-4 The number of threads in the running python3.11.exe process on Windows

In Linux, you can see the expected number of threads – 3:

~/Chapter1$ ps -aT
PID SPID TTY TIME CMD
17 17 pts/0 00:00:00 mc
45 45 pts/2 00:00:00 python3
45 46 pts/2 00:00:00 python3
45 47 pts/2 00:00:00 python3
54 54 pts/1 00:00:00 ps
Stack Trace (Backtrace, Traceback)
I should distinguish Python source code tracebacks (which we call managed stack traces)
and unmanaged (native) ones from the Python compiler and interpreter that compiles to
and executes Python byte code. You will see this distinction in some chapters for several
case studies and how to get both traces. But, for now, I will just show the difference.
Listing 1-3 shows managed stack trace. Listing 1-4 shows the corresponding unmanaged
Linux stack trace with debugging symbols (the most recent call first). Listing 1-5 shows
the corresponding unmanaged Windows stack trace without debugging symbols (the
most recent call first).

Traceback (most recent call last):


File "process.py", line 14, in <module>
main()
File "process.py", line 4, in main
foo()
File "process.py", line 7, in foo
bar()
File "process.py", line 11, in bar
time.sleep(1)
Listing 1-3 Managed Stack Trace from the Execution of the Python Script from Listing 1-1

#0 0x00007f6bc84e6b97 in __GI___select (nfds=0, readfds=0x0,


writefds=0x0, exceptfds=0x0, timeout=0x7ffc60288fe0)
at ../sysdeps/unix/sysv/linux/select.c:41
#1 0x00000000004e8965 in pysleep (secs=<optimized out>) at
../Modules/timemodule.c:1829
#2 time_sleep (self=<optimized out>, obj=<optimized out>,
self=<optimized out>, obj=<optimized out>)
at ../Modules/timemodule.c:371
#3 0x00000000005d8711 in _PyMethodDef_RawFastCallKeywords
(method=0x82dbe0 <time_methods+288>,
self=<module at remote 0x7f6bc800dc78>,
args=0x7f6bc80c4550, nargs=<optimized out>, kwnames=<optimized
out>)
at ../Objects/call.c:644
#4 0x000000000054b330 in _PyCFunction_FastCallKeywords
(kwnames=<optimized out>, nargs=<optimized out>,
args=0x7f6bc80c4550, func=<built-in method sleep of module
object at remote 0x7f6bc800dc78>)
at ../Objects/call.c:730
#5 call_function (pp_stack=0x7ffc60289150, oparg=<optimized
out>, kwnames=<optimized out>) at ../Python/ceval.c:4568
#6 0x00000000005524cd in _PyEval_EvalFrameDefault (f=
<optimized out>, throwflag=<optimized out>)
at ../Python/ceval.c:3093
#7 0x00000000005d91fc in PyEval_EvalFrameEx (throwflag=0,
f=Frame 0x7f6bc80c43d8, for file process.py, line 11, in
bar ()) at ../Python/ceval.c:547
#8 function_code_fastcall (globals=<optimized out>, nargs=
<optimized out>, args=<optimized out>, co=<optimized out>)
at ../Objects/call.c:283
#9 _PyFunction_FastCallKeywords (func=<optimized out>, stack=
<optimized out>, nargs=<optimized out>,
kwnames=<optimized out>) at ../Objects/call.c:408
#10 0x000000000054e5ac in call_function (kwnames=0x0, oparg=
<optimized out>, pp_stack=<synthetic pointer>)
at ../Python/ceval.c:4616
#11 _PyEval_EvalFrameDefault (f=<optimized out>, throwflag=
<optimized out>) at ../Python/ceval.c:3124
#12 0x00000000005d91fc in PyEval_EvalFrameEx (throwflag=0,
f=Frame 0x7f6bc80105e8, for file process.py, line 7, in foo
()) at ../Python/ceval.c:547
#13 function_code_fastcall (globals=<optimized out>, nargs=
<optimized out>, args=<optimized out>, co=<optimized out>)
at ../Objects/call.c:283
#14 _PyFunction_FastCallKeywords (func=<optimized out>, stack=
<optimized out>, nargs=<optimized out>,
kwnames=<optimized out>) at ../Objects/call.c:408
--Type <RET> for more, q to quit, c to continue without paging-
-
#15 0x000000000054e5ac in call_function (kwnames=0x0, oparg=
<optimized out>, pp_stack=<synthetic pointer>)
at ../Python/ceval.c:4616
#16 _PyEval_EvalFrameDefault (f=<optimized out>, throwflag=
<optimized out>) at ../Python/ceval.c:3124
#17 0x00000000005d91fc in PyEval_EvalFrameEx (throwflag=0,
f=Frame 0x205ade8, for file process.py, line 4, in main ())
at ../Python/ceval.c:547
#18 function_code_fastcall (globals=<optimized out>, nargs=
<optimized out>, args=<optimized out>, co=<optimized out>)
at ../Objects/call.c:283
#19 _PyFunction_FastCallKeywords (func=<optimized out>, stack=
<optimized out>, nargs=<optimized out>,
kwnames=<optimized out>) at ../Objects/call.c:408
#20 0x000000000054e5ac in call_function (kwnames=0x0, oparg=
<optimized out>, pp_stack=<synthetic pointer>)
at ../Python/ceval.c:4616
#21 _PyEval_EvalFrameDefault (f=<optimized out>, throwflag=
<optimized out>) at ../Python/ceval.c:3124
#22 0x000000000054bcc2 in PyEval_EvalFrameEx (throwflag=0,
f=Frame 0x7f6bc80ab9f8, for file process.py, line 14, in
<module> ()) at ../Python/ceval.c:547
#23 _PyEval_EvalCodeWithName (_co=<optimized out>, globals=
<optimized out>, locals=<optimized out>,
args=<optimized out>, argcount=<optimized out>,
kwnames=0x0, kwargs=0x0, kwcount=<optimized out>, kwstep=2,
defs=0x0, defcount=0, kwdefs=0x0, closure=0x0, name=0x0,
qualname=0x0) at ../Python/ceval.c:3930
#24 0x000000000054e0a3 in PyEval_EvalCodeEx (closure=0x0,
kwdefs=0x0, defcount=0, defs=0x0, kwcount=0, kws=0x0,
argcount=0, args=0x0, locals=<optimized out>, globals=
<optimized out>, _co=<optimized out>)
at ../Python/ceval.c:3959
#25 PyEval_EvalCode (co=<optimized out>, globals=<optimized
out>, locals=<optimized out>) at ../Python/ceval.c:524
#26 0x0000000000630ce2 in run_mod (mod=<optimized out>,
filename=<optimized out>,
globals={'__name__': '__main__', '__doc__': None,
'__package__': None, '__loader__':
<SourceFileLoader(name='__main__', path='process.py') at remote
0x7f6bc803dfd0>, '__spec__': None, '__annotations__': {},
'__builtins__': <module at remote 0x7f6bc8102c28>, '__file__':
'process.py', '__cached__': None, 'time': <module at remote
0x7f6bc800dc78>, 'main': <function at remote 0x7f6bc80791e0>,
'foo': <function at remote 0x7f6bc7f69c80>, 'bar': <function at
remote 0x7f6bc7f69d08>},
locals={'__name__': '__main__', '__doc__': None,
'__package__': None, '__loader__':
<SourceFileLoader(name='__main__', path='process.py') at remote
0x7f6bc803dfd0>, '__spec__': None, '__annotations__': {},
'__builtins__': <module at rem--Type <RET> for more, q to quit,
c to continue without paging--
ote 0x7f6bc8102c28>, '__file__': 'process.py', '__cached__':
None, 'time': <module at remote 0x7f6bc800dc78>, 'main':
<function at remote 0x7f6bc80791e0>, 'foo': <function at remote
0x7f6bc7f69c80>, 'bar': <function at remote 0x7f6bc7f69d08>},
flags=<optimized out>, arena=<optimized out>) at
../Python/pythonrun.c:1035
#27 0x0000000000630d97 in PyRun_FileExFlags (fp=0x2062390,
filename_str=<optimized out>, start=<optimized out>,
globals={'__name__': '__main__', '__doc__': None,
'__package__': None, '__loader__':
<SourceFileLoader(name='__main__', path='process.py') at remote
0x7f6bc803dfd0>, '__spec__': None, '__annotations__': {},
'__builtins__': <module at remote 0x7f6bc8102c28>, '__file__':
'process.py', '__cached__': None, 'time': <module at remote
0x7f6bc800dc78>, 'main': <function at remote 0x7f6bc80791e0>,
'foo': <function at remote 0x7f6bc7f69c80>, 'bar': <function at
remote 0x7f6bc7f69d08>},
locals={'__name__': '__main__', '__doc__': None,
'__package__': None, '__loader__':
<SourceFileLoader(name='__main__', path='process.py') at remote
0x7f6bc803dfd0>, '__spec__': None, '__annotations__': {},
'__builtins__': <module at remote 0x7f6bc8102c28>, '__file__':
'process.py', '__cached__': None, 'time': <module at remote
0x7f6bc800dc78>, 'main': <function at remote 0x7f6bc80791e0>,
'foo': <function at remote 0x7f6bc7f69c80>, 'bar': <function at
remote 0x7f6bc7f69d08>}, closeit=1, flags=0x7ffc6028989c) at
../Python/pythonrun.c:988
#28 0x00000000006319ff in PyRun_SimpleFileExFlags
(fp=0x2062390, filename=<optimized out>, closeit=1,
flags=0x7ffc6028989c) at ../Python/pythonrun.c:429
#29 0x000000000065432e in pymain_run_file (p_cf=0x7ffc6028989c,
filename=<optimized out>, fp=0x2062390)
at ../Modules/main.c:427
#30 pymain_run_filename (cf=0x7ffc6028989c,
pymain=0x7ffc60289970) at ../Modules/main.c:1627
#31 pymain_run_python (pymain=0x7ffc60289970) at
../Modules/main.c:2877
#32 pymain_main (pymain=<optimized out>, pymain=<optimized
out>) at ../Modules/main.c:3038
#33 0x000000000065468e in _Py_UnixMain (argc=<optimized out>,
argv=<optimized out>) at ../Modules/main.c:3073
#34 0x00007f6bc841a09b in __libc_start_main (main=0x4bc560
<main>, argc=2, argv=0x7ffc60289ab8, init=<optimized out>,
fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7ffc60289aa8) at ../csu/libc-start.c:308
#35 0x00000000005e0e8a in _start () at ../Modules/main.c:797
Listing 1-4 Unmanaged Linux Backtrace from the Execution of the Python Script from Listing 1-1 with
Debugging Symbols

00 00000090`7e1ef0a8
00007ff9`8c44fcf9 ntdll!NtWaitForMultipleObjects+0x14
01 00000090`7e1ef0b0
00007ff9`8c44fbfe KERNELBASE!WaitForMultipleObjectsEx+0xe9
02 00000090`7e1ef390
00007ff8`ef943986 KERNELBASE!WaitForMultipleObjects+0xe
03 00000090`7e1ef3d0
00007ff8`ef94383d python311!PyTraceBack_Print_Indented+0x35a
04 00000090`7e1ef430
00007ff8`ef81a6b2 python311!PyTraceBack_Print_Indented+0x211
05 00000090`7e1ef460
00007ff8`ef82fa77 python311!PyEval_EvalFrameDefault+0x8f2
06 00000090`7e1ef670
00007ff8`ef82f137 python311!PyMapping_Check+0x1eb
07 00000090`7e1ef6b0
00007ff8`ef82d80a python311!PyEval_EvalCode+0x97
08 00000090`7e1ef730
00007ff8`ef82d786 python311!PyMapping_Items+0x11e
09 00000090`7e1ef760
00007ff8`ef97a17e python311!PyMapping_Items+0x9a
0a 00000090`7e1ef7a0
00007ff8`ef7e33a5 python311!PyThread_tss_is_created+0x53ce
0b 00000090`7e1ef810
00007ff8`ef8da620 python311!PyRun_SimpleFileObject+0x11d
0c 00000090`7e1ef880
00007ff8`ef8daaef python311!PyRun_AnyFileObject+0x54
0d 00000090`7e1ef8b0
00007ff8`ef8dab5f python311!Py_MakePendingCalls+0x38f
0e 00000090`7e1ef980
00007ff8`ef8db964 python311!Py_MakePendingCalls+0x3ff
0f 00000090`7e1ef9b0
00007ff8`ef8db7f5 python311!Py_RunMain+0x184
10 00000090`7e1efa20
00007ff8`ef8260d9 python311!Py_RunMain+0x15
11 00000090`7e1efa50
00007ff6`aefe1230 python311!Py_Main+0x25
12 00000090`7e1efaa0 00007ff9`8e1c26ad python+0x1230
13 00000090`7e1efae0
00007ff9`8ef6a9f8 KERNEL32!BaseThreadInitThunk+0x1d
14 00000090`7e1efb10
00000000`00000000 ntdll!RtlUserThreadStart+0x28
Listing 1-5 Unmanaged Windows Stack Trace from the Execution of the Python Script from Listing 1-1
Without Debugging Symbols

Note Each thread has its own stack trace (backtrace).

Symbol Files
Symbol files allow a debugger to map memory addresses to symbolic information such as
function and variable names. For example, if you download and apply symbol files to the
Windows example above, you get a much better and more accurate stack trace, as shown
in Listing 1-6.

00 00000090`7e1ef0a8
00007ff9`8c44fcf9 ntdll!NtWaitForMultipleObjects+0x14
01 00000090`7e1ef0b0
00007ff9`8c44fbfe KERNELBASE!WaitForMultipleObjectsEx+0xe9
02 00000090`7e1ef390
00007ff8`ef943986 KERNELBASE!WaitForMultipleObjects+0xe
03 00000090`7e1ef3d0
00007ff8`ef94383d python311!pysleep+0x11a
04 00000090`7e1ef430
00007ff8`ef81a6b2 python311!time_sleep+0x2d
05 00000090`7e1ef460
00007ff8`ef82fa77 python311!_PyEval_EvalFrameDefault+0x8f2
06 (Inline Function) --------`-------
- python311!_PyEval_EvalFrame+0x1e
07 00000090`7e1ef670
00007ff8`ef82f137 python311!_PyEval_Vector+0x77
08 00000090`7e1ef6b0
00007ff8`ef82d80a python311!PyEval_EvalCode+0x97
09 00000090`7e1ef730
00007ff8`ef82d786 python311!run_eval_code_obj+0x52
0a 00000090`7e1ef760
00007ff8`ef97a17e python311!run_mod+0x72
0b 00000090`7e1ef7a0
00007ff8`ef7e33a5 python311!pyrun_file+0x196b66
0c 00000090`7e1ef810
00007ff8`ef8da620 python311!_PyRun_SimpleFileObject+0x11d
0d 00000090`7e1ef880
00007ff8`ef8daaef python311!_PyRun_AnyFileObject+0x54
0e 00000090`7e1ef8b0
00007ff8`ef8dab5f python311!pymain_run_file_obj+0x10b
0f 00000090`7e1ef980
00007ff8`ef8db964 python311!pymain_run_file+0x63
10 00000090`7e1ef9b0
00007ff8`ef8db7f5 python311!pymain_run_python+0x140
11 00000090`7e1efa20
00007ff8`ef8260d9 python311!Py_RunMain+0x15
12 00000090`7e1efa50
00007ff6`aefe1230 python311!Py_Main+0x25
13 (Inline Function) --------`-------
- python!invoke_main+0x22
14 00000090`7e1efaa0
00007ff9`8e1c26ad python!__scrt_common_main_seh+0x10c
15 00000090`7e1efae0
00007ff9`8ef6a9f8 KERNEL32!BaseThreadInitThunk+0x1d
16 00000090`7e1efb10
00000000`00000000 ntdll!RtlUserThreadStart+0x28
Listing 1-6 Unmanaged Windows Stack Trace from the Execution of the Python Script from Listing 1-1
with Debugging Symbols
Module
Like the distinction between managed and unmanaged stack traces, there is a difference
between Python modules (which may correspond to files in traceback) and native
modules such as DLLs in Windows and .so files in Linux, which are loaded into memory
when you execute the Python compiler/interpreter. For example, the following shared
libraries are loaded in Linux for the simple multithreaded example from Listing 1-2:

~/Chapter1$ pmap 60
60: python3 process.py
0000000000400000 132K r---- python3.7
0000000000421000 2256K r-x-- python3.7
0000000000655000 1712K r---- python3.7
0000000000801000 4K r---- python3.7
0000000000802000 664K rw--- python3.7
00000000008a8000 140K rw--- [ anon ]
0000000001fff000 660K rw--- [ anon ]
00007f6bc7f69000 1684K rw--- [ anon ]
00007f6bc810e000 2964K r---- locale-archive
00007f6bc83f3000 12K rw--- [ anon ]
00007f6bc83f6000 136K r---- libc-2.28.so
00007f6bc8418000 1308K r-x-- libc-2.28.so
00007f6bc855f000 304K r---- libc-2.28.so
00007f6bc85ab000 4K ----- libc-2.28.so
00007f6bc85ac000 16K r---- libc-2.28.so
00007f6bc85b0000 8K rw--- libc-2.28.so
00007f6bc85b2000 16K rw--- [ anon ]
00007f6bc85b6000 52K r---- libm-2.28.so
00007f6bc85c3000 636K r-x-- libm-2.28.so
00007f6bc8662000 852K r---- libm-2.28.so
00007f6bc8737000 4K r---- libm-2.28.so
00007f6bc8738000 4K rw--- libm-2.28.so
00007f6bc8739000 8K rw--- [ anon ]
00007f6bc873b000 12K r---- libz.so.1.2.11
00007f6bc873e000 72K r-x-- libz.so.1.2.11
00007f6bc8750000 24K r---- libz.so.1.2.11
00007f6bc8756000 4K ----- libz.so.1.2.11
00007f6bc8757000 4K r---- libz.so.1.2.11
00007f6bc8758000 4K rw--- libz.so.1.2.11
00007f6bc8759000 16K r---- libexpat.so.1.6.8
00007f6bc875d000 132K r-x-- libexpat.so.1.6.8
00007f6bc877e000 80K r---- libexpat.so.1.6.8
00007f6bc8792000 4K ----- libexpat.so.1.6.8
00007f6bc8793000 8K r---- libexpat.so.1.6.8
00007f6bc8795000 4K rw--- libexpat.so.1.6.8
00007f6bc8796000 4K r---- libutil-2.28.so
00007f6bc8797000 4K r-x-- libutil-2.28.so
00007f6bc8798000 4K r---- libutil-2.28.so
00007f6bc8799000 4K r---- libutil-2.28.so
00007f6bc879a000 4K rw--- libutil-2.28.so
00007f6bc879b000 4K r---- libdl-2.28.so
00007f6bc879c000 4K r-x-- libdl-2.28.so
00007f6bc879d000 4K r---- libdl-2.28.so
00007f6bc879e000 4K r---- libdl-2.28.so
00007f6bc879f000 4K rw--- libdl-2.28.so
00007f6bc87a0000 24K r---- libpthread-2.28.so
00007f6bc87a6000 60K r-x-- libpthread-2.28.so
00007f6bc87b5000 24K r---- libpthread-2.28.so
00007f6bc87bb000 4K r---- libpthread-2.28.so
00007f6bc87bc000 4K rw--- libpthread-2.28.so
00007f6bc87bd000 16K rw--- [ anon ]
00007f6bc87c1000 4K r---- libcrypt-2.28.so
00007f6bc87c2000 24K r-x-- libcrypt-2.28.so
00007f6bc87c8000 8K r---- libcrypt-2.28.so
00007f6bc87ca000 4K ----- libcrypt-2.28.so
00007f6bc87cb000 4K r---- libcrypt-2.28.so
00007f6bc87cc000 4K rw--- libcrypt-2.28.so
00007f6bc87cd000 192K rw--- [ anon ]
00007f6bc8801000 28K r--s- gconv-modules.cache
00007f6bc8808000 4K r---- ld-2.28.so
00007f6bc8809000 120K r-x-- ld-2.28.so
00007f6bc8827000 32K r---- ld-2.28.so
00007f6bc882f000 4K r---- ld-2.28.so
00007f6bc8830000 4K rw--- ld-2.28.so
00007f6bc8831000 4K rw--- [ anon ]
00007ffc6026a000 132K rw--- [ stack ]
00007ffc60356000 16K r---- [ anon ]
00007ffc6035a000 4K r-x-- [ anon ]
total 14700K
The Windows version has the following loaded modules:

00007ff6`aefe0000 00007ff6`aeffa000 python python.exe


00007ff8`ef7e0000 00007ff8`efdad000 python311 python311.dll
00007ff9`62950000 00007ff9`6296b000 VCRUNTIME140
VCRUNTIME140.dll
00007ff9`7f1e0000 00007ff9`7f1ea000 VERSION VERSION.dll
00007ff9`8bce0000 00007ff9`8bd08000 bcrypt bcrypt.dll
00007ff9`8c3f0000 00007ff9`8c793000 KERNELBASE KERNELBASE.dll
00007ff9`8c840000 00007ff9`8c951000 ucrtbase ucrtbase.dll
00007ff9`8c960000 00007ff9`8c9db000 bcryptprimitives
bcryptprimitives.dll
00007ff9`8d150000 00007ff9`8d1c1000 WS2_32 WS2_32.dll
00007ff9`8d1d0000 00007ff9`8d2e7000 RPCRT4 RPCRT4.dll
00007ff9`8dd50000 00007ff9`8ddf7000 msvcrt msvcrt.dll
00007ff9`8ded0000 00007ff9`8df7e000 ADVAPI32 ADVAPI32.dll
00007ff9`8e1b0000 00007ff9`8e272000 KERNEL32 KERNEL32.DLL
00007ff9`8e280000 00007ff9`8e324000 sechost sechost.dll
00007ff9`8ef10000 00007ff9`8f124000 ntdll ntdll.dll

Memory Dump
A process memory can be saved in a memory dump file.

An undigested and voluminous mass of information about a problem or the state of a


system and most especially one consisting of hex runes describing the byte-by-byte
state of memory.
Eric S. Raymond, The New Hacker’s Dictionary, Third Edition

These memory dumps are also called core dumps in Linux. It is also possible to get a
kernel memory dump and a dump of physical memory (also called a complete memory
dump in Windows). Figure 1-5 shows different memory dump types.

Figure 1-5 Memory dump types

Memory dumps may be useful for debugging hard-to-reproduce intermittent


problems. This approach is called postmortem debugging. You will see some case studies
in the following chapters.

Crash
To fail suddenly. “Has the system just crashed?” “Something crashed the OS!” Also
used transitively to indicate the cause of the crash (usually a person or a program, or
both). “Those idiots playing SPACEWAR crashed the system.”
Eric S. Raymond, The New Hacker’s Dictionary, Third Edition.

When something illegal happens inside a process thread, such as when memory
outside its available range is accessed or you write to read-only memory, the operating
system reports the error and terminates the process. It may also save the process
memory into a memory dump file. The process then disappears from the list of available
processes.

Hang
1. To wait for an event that will never occur. “The system is hanging because it can’t
read from the crashed drive.”

2. To wait for an event to occur. “The program displays a menu and then hangs until
you type a character.”
Eric S. Raymond, The New Hacker’s Dictionary, Third Edition

Threads interact with other threads, including other processes’ threads. These
interactions can be viewed as sending messages and waiting for the responses. Some
processes may be critical because their threads process messages from many other
threads from other processes. If threads from such a critical process stop sending
responses, all other waiting threads are blocked. A deadlock is when two threads are
waiting for each other. When hanging, the process continues to be present in the list of
available processes. There are also processes (critical components) that, when their
threads hang, block threads from many other processes (noncritical components). Figure
1-6 depicts such components and their interaction abstracted via messages in the normal
scenario, and Figure 1-7 shows the abnormal scenario when noncritical components are
blocked and waiting for responses because the critical components are deadlocked.
Figure 1-6 Request and response interaction between critical and noncritical system components
Figure 1-7 Blocked and deadlocked components

Summary
In this chapter, you learned the fundamental vocabulary you will use in subsequent
chapters. The next chapter introduces a pattern-oriented debugging approach.
© The Author(s), under exclusive license to APress Media, LLC, part of Springer
Nature 2024
D. Vostokov, Python Debugging for AI, Machine Learning, and Cloud Computing
https://doi.org/10.1007/978-1-4842-9745-2_2

2. Pattern-Oriented Debugging
Dmitry Vostokov1

(1) Dalkey, Dublin, Ireland

This chapter introduces the pattern-oriented debugging process


approach and the pattern languages you will use in subsequent
chapters.

The History of the Idea


The idea of using patterns in debugging is not new1. Earlier, such
patterns came in two types: bug patterns2 and debug patterns3. Before
2000, only a few debugging-related patterns could be found, such as the
Debug Printing Method4.
Bug patterns are usually specific patterns for specific languages and
platforms. By bugs, we mean software defects. Usually, these are related
to the source code but can also be related to configuration and data
models.
Using source code as a starting point for debugging is only possible
for a limited number of scenarios, such as when you have a Python
stack trace. However, there are many cases when the starting point for
source code investigation is unknown. Here, a well-defined process may
benefit. A number of debugging processes were proposed in the past,
including multidisciplinary approaches5.
The phrase “pattern-oriented debugging” appeared around 1987-
1988 in the context of patterns of process interaction6. It is not the
same as the “pattern-oriented debugging process” proposed in 20147
as further development of unified debugging patterns that were
introduced in 20108. Since then, these patterns have been used for
successfully teaching Windows debugging of unmanaged (native,
Win64, C, C++) and managed (.NET, C#) code9 for almost a decade,
starting in 2013. Overall, this pattern-oriented approach can be traced
to our earlier presentation published as a book in 201110. In it, we
apply the same pattern-oriented process to Python debugging in cloud
and machine learning environments.

Patterns and Analysis Patterns


Before looking at the debugging process, a few words about patterns in
the context of diagnostics and debugging. By a pattern, we mean a
common recurrent identifiable set of indicators (symptoms, signs). By
an analysis pattern, we mean a common recurrent analysis technique
and method of pattern identification in a specific context. By pattern
language, we mean common names of patterns and analysis patterns
used for communication.

Development Process
Let’s first look at the traditional software development process stages.
Figure 2-1 abstracts them from several development processes,
including waterfall and iterative ones.
Figure 2-1 Stages of the typical software development process

Development Patterns
For each stage, there exists some pattern language such as a vocabulary
of solutions to common recurrent identifiable problems with grammar,
semantics, and pragmatics. Figure 2-2 also includes software usage and
presentation patterns for human-computer interaction. In this book, I
assume you have familiarity with such pattern languages (some
references are provided below).
Figure 2-2 Typical software development pattern languages

Debugging Process and Patterns


The debugging process mirrors the development process and
development patterns, as shown in Figure 2-3. Let’s look at each stage.
Figure 2-3 Stages of the pattern-oriented debugging process

Elementary Diagnostics Patterns


Elementary software diagnostics patterns got inspiration from the
Elemental Design Patterns book title11, but they are different and
correspond to requirements from the software development process.
These are what software users experience, and the requirement is to
eliminate such experiences via debugging.
Debugging Analysis Patterns
You need to diagnose the right problem before doing any debugging.
Debugging analysis patterns correspond to software diagnostics. For
example, in memory dump analysis, there are analysis patterns such as
Managed Code Exception, Managed Stack Trace, Stack Overflow,
Deadlock, Spiking Thread, and many others. There are hundreds of
them12. Trace and log analysis patterns such as Thread of Activity,
Discontinuity, Time Delta, Counter Value, State Dump, and many
more are also included in this category13. We look at the most common
of them in Chapter 4.

Debugging Architecture Patterns


Debugging architecture patterns are partly inspired by POSA14, for
example, Debug Event Subscription/Notification. They are more
high-level than design patterns that may differ for specific technologies,
for example, object-oriented and functional.

Debugging Design Patterns


Debugging design patterns are partly inspired by the GoF design
pattern approach15, for example, Punctuated Execution.
Both debugging architecture and debugging design patterns pertain
to the development of debugging tools and to actual debugging
architectures and designs as reusable solutions to common recurrent
debugging problems in specific contexts.

Debugging Implementation Patterns


Debugging implementation patterns are patterns of debugging
strategies and core debugging techniques, such as Break-in, Code
Breakpoint, Data Breakpoint, and others covered in subsequent
chapters in Python debugging case studies.

Debugging Usage Patterns


Debugging usage patterns are about debugging pragmatics of reusable
debugging scenarios: how, what, when, and where to use the previous
debugging pattern categories, such as using data breakpoints in user
(process) and kernel space debugging.

Debugging Presentation Patterns


Debugging presentation patterns are about user interface and
interaction design16, for example, watch dialog. These patterns are also
related to debugging usage. We cover such patterns in the chapter
devoted to existing Python IDEs and their usage for Python debugging.
In our opinion, recent Python debugging books17 correspond to
debugging implementation, usage, and presentation. Automated
debugging18 belongs to debugging architecture and design. In this book,
we extract some of this knowledge into corresponding debugging
pattern languages, combine them with pattern-oriented software
diagnostics, and form a novel pattern-oriented Python debugging
approach in the context of machine learning and cloud computing
environments.

Summary
In this chapter, you learned about the pattern-oriented debugging
process, its stages, and corresponding pattern languages. The
subsequent chapters provide examples of debugging patterns from
each category from a Python programming perspective. The next
chapter is about the first stage and its patterns: elementary diagnostics
patterns.

Footnotes
1 Mehdi Amoui et al., “A Pattern Language for Software Debugging,” International
Journal of Computer Science, vol. 1, no. 3, pp. 218-224, 2006.
https://stargroup.uwaterloo.ca/~mamouika/papers/pdf/IJCS.2006
.pdf

2 Eric Allen, Bug Patterns in Java, 2002 (ISBN-13: 978-1590590614)


3 https://en.wikipedia.org/wiki/Debugging_pattern

4 Linda Rising, The Pattern Almanac 2000, p. 154 (ISBN-13: 978-0201615678)

5 Robert Charles Metzger, Debugging by Thinking: A Multidisciplinary Approach, 2003


(ISBN-13: 978-1555583071)

6 Alfred A. Hough and Janice E. Cuny, “Initial experiences with a pattern-oriented


parallel debugger.” PADD ‘88: Proceedings of the 1988 ACM SIGPLAN and SIGOPS
workshop on Parallel and distributed debugging November 1988 Pages 195–205
https://doi.org/10.1145/68210.69234

7 Dmitry Vostokov, Pattern-Oriented Debugging Process, in Theoretical Software


Diagnostics: Collected Articles, Third Edition, 2020 (ISBN-13: 978-1912636334), pp.
197-199

8 Ibid., “Analysis, Architectural, Design, Implementation and Usage Debugging


Patterns,” p. 129

9 Accelerated Windows Debugging 4D, Third Edition, 2022 (ISBN-13: 978-


1912636532)

10 Dmitry Vostokov, Introduction to Pattern-Driven Software Problem Solving, 2011


(ISBN-13: 978-1908043177)

11 Jason McC. Smith, Elemental Design Patterns, 2012 (ISBN-13: 978-0321711922)

12 Dmitry Vostokov, Encyclopedia of Crash Dump Analysis Patterns: Detecting


Abnormal Software Structure and Behavior in Computer Memory, Third Edition, 2020
(ISBN-13: 978-1912636303)
Another random document with
no related content on Scribd:
heureux qu’en entendant le galant abbé de San-Lucar, dona Elvire et
Philippe occupés à discuter un cas de conscience. Cependant,
malgré les soins prodigieux que le seigneur don Juan Belvidéro
donnait à sa personne, les jours de la décrépitude arrivèrent; avec
cet âge de douleur, vinrent les cris de l’impuissance, cris d’autant
plus déchirants, que plus riches étaient les souvenirs de sa
bouillante jeunesse et de sa voluptueuse maturité. Cet homme, en
qui le dernier degré de la raillerie était d’engager les autres à croire
aux lois et aux principes dont il se moquait, s’endormait le soir sur un
peut-être! Ce modèle du bon ton, ce duc, vigoureux dans une orgie,
superbe dans les cours, gracieux auprès des femmes dont les
cœurs avaient été tordus par lui comme un paysan tord un lien
d’osier, cet homme de génie avait une pituite opiniâtre, une sciatique
importune, une goutte brutale. Il voyait ses dents le quittant comme
à la fin d’une soirée, les dames les plus blanches, les mieux parées,
s’en vont, une à une, laissant le salon désert et démeublé. Enfin ses
mains hardies tremblèrent, ses jambes sveltes chancelèrent, et un
soir l’apoplexie lui pressa le cou de ses mains crochues et glaciales.
Depuis ce jour fatal, il devint morose et dur. Il accusait le
dévouement de son fils et de sa femme, en prétendant parfois que
leurs soins touchants et délicats ne lui étaient si tendrement
prodigués que parce qu’il avait placé toute sa fortune en rentes
viagères. Elvire et Philippe versaient alors des larmes amères et
redoublaient de caresses auprès du malicieux vieillard, dont la voix
cassée devenait affectueuse pour leur dire:—«Mes amis, ma chère
femme, vous me pardonnez, n’est-ce pas? Je vous tourmente un
peu. Hélas! grand Dieu! comment te sers-tu de moi pour éprouver
ces deux célestes créatures? Moi, qui devrais être leur joie, je suis
leur fléau.» Ce fut ainsi qu’il les enchaîna au chevet de son lit, leur
faisant oublier des mois entiers d’impatience et de cruauté par une
heure où, pour eux, il déployait les trésors toujours nouveaux de sa
grâce et d’une fausse tendresse. Système paternel qui lui réussit
infiniment mieux que celui dont avait usé jadis son père envers lui.
Enfin, il parvint à un tel degré de maladie que, pour le mettre au lit, il
fallait le manœuvrer comme une felouque entrant dans un chenal
dangereux. Puis le jour de la mort arriva. Ce brillant et sceptique
personnage, dont l’entendement survivait seul à la plus affreuse de
toutes les destructions, se vit entre un médecin et un confesseur,
ses deux antipathies. Mais il fut jovial avec eux. N’y avait-il pas, pour
lui, une lumière scintillante derrière le voile de l’avenir? Sur cette
toile, de plomb pour les autres et diaphane pour lui, les légères, les
ravissantes délices de la jeunesse se jouaient comme des ombres.
Ce fut par une belle soirée d’été que don Juan sentit les
approches de la mort. Le ciel de l’Espagne était d’une admirable
pureté, les orangers parfumaient l’air, les étoiles distillaient de vives
et fraîches lumières, la nature semblait lui donner des gages certains
de sa résurrection, un fils pieux et obéissant le contemplait avec
amour et respect. Vers onze heures, il voulut rester seul avec cet
être candide.
—Philippe, lui dit-il d’une voix si tendre et si affectueuse que le
jeune homme tressaillit et pleura de bonheur. Jamais ce père
inflexible n’avait prononcé ainsi: Philippe!—Écoute-moi, mon fils,
reprit le moribond. Je suis un grand pécheur. Aussi ai-je pensé,
pendant toute ma vie, à ma mort. Jadis je fus l’ami du grand pape
Jules II. Cet illustre pontife craignit que l’excessive irritation de mes
sens ne me fît commettre quelque péché mortel entre le moment où
j’expirerais et celui où j’aurais reçu les saintes huiles; il me fit présent
d’une fiole dans laquelle existe l’eau sainte jaillie autrefois des
rochers, dans le désert. J’ai gardé le secret sur cette dilapidation du
trésor de l’Église, mais je suis autorisé à révéler ce mystère à mon
fils, in articulo mortis. Vous trouverez cette fiole dans le tiroir de cette
table gothique qui n’a jamais quitté le chevet de mon lit... Le
précieux cristal pourra vous servir encore, mon bien-aimé Philippe.
Jurez-moi, par votre salut éternel, d’exécuter ponctuellement mes
ordres?
Philippe regarda son père. Don Juan se connaissait trop à
l’expression des sentiments humains pour ne pas mourir en paix sur
la foi d’un tel regard, comme son père était mort au désespoir sur la
foi du sien.
—Tu méritais un autre père, reprit don Juan. J’ose t’avouer, mon
enfant, qu’au moment où le respectable abbé de San-Lucar
m’administrait le viatique, je pensais à l’incompatibilité de deux
puissances aussi étendues que celles du diable et de Dieu...
—Oh! mon père!
—Et je me disais que, quand Satan fera sa paix, il devra, sous
peine d’être un grand misérable, stipuler le pardon de ses adhérents.
Cette pensée me poursuit. J’irais donc en enfer, mon fils, si tu
n’accomplissais pas mes volontés.
—Oh! dites-les-moi promptement, mon père!
—Aussitôt que j’aurai fermé les yeux, reprit don Juan, dans
quelques minutes peut-être, tu prendras mon corps, tout chaud
même, et tu l’étendras sur une table au milieu de cette chambre.
Puis tu éteindras cette lampe; la lueur des étoiles doit te suffire. Tu
me dépouilleras de mes vêtements; et pendant que tu réciteras des
Pater et des Ave en élevant ton âme à Dieu, tu auras soin
d’humecter, avec cette eau sainte, mes yeux, mes lèvres, toute la
tête d’abord, puis successivement les membres et le corps; mais,
mon cher fils, la puissance de Dieu est si grande, qu’il ne faudra
t’étonner de rien!
Ici, don Juan, qui sentit la mort venir, ajouta d’une voix terrible:—
Tiens bien le flacon. Puis il expira doucement dans les bras d’un fils
dont les larmes abondantes coulèrent sur sa face ironique et blême.
Il était environ minuit quand don Philippe Belvidéro plaça le
cadavre de son père sur la table. Après en avoir baisé le front
menaçant et les cheveux gris, il éteignit la lampe. La lueur douce,
produite par la clarté de la lune, dont les reflets bizarres illuminaient
la campagne, permit au pieux Philippe d’entrevoir indistinctement le
corps de son père, comme quelque chose de blanc au milieu de
l’ombre. Le jeune homme imbiba un linge dans la liqueur, et, plongé
dans la prière, il oignit fidèlement cette tête sacrée au milieu d’un
profond silence. Il entendait bien des frémissements indescriptibles,
mais il les attribuait aux jeux de la brise dans les cimes des arbres.
Quand il eut mouillé le bras droit, il se sentit fortement étreindre le
cou par un bras jeune et vigoureux, le bras de son père! Il jeta un cri
déchirant, et laissa tomber la fiole, qui se cassa. La liqueur
s’évapora. Les gens du château accoururent, armés de flambeaux.
Ce cri les avait épouvantés et surpris, comme si la trompette du
jugement dernier eût ébranlé l’univers. En un moment, la chambre
fut pleine de monde. La foule tremblante aperçut don Philippe
évanoui, mais retenu par le bras puissant de son père, qui lui serrait
le cou. Puis, chose surnaturelle, l’assistance vit la tête de don Juan,
aussi jeune, aussi belle que celle de l’Antinoüs; une tête aux
cheveux noirs, aux yeux brillants, à la bouche vermeille et qui
s’agitait effroyablement sans pouvoir remuer le squelette auquel elle
appartenait. Un vieux serviteur cria:—Miracle! Et tous ces Espagnols
répétèrent:—Miracle! Trop pieuse pour admettre les mystères de la
magie, dona Elvire envoya chercher l’abbé de San-Lucar. Lorsque le
prieur contempla de ses yeux le miracle, il résolut d’en profiter en
homme d’esprit et en abbé qui ne demandait pas mieux que
d’augmenter ses revenus. Déclarant aussitôt que le seigneur don
Juan serait infailliblement canonisé, il indiqua la cérémonie de
l’apothéose dans son couvent, qui désormais s’appellerait, dit-il,
San-Juan-de-Lucar. A ces mots, la tête fit une grimace assez
facétieuse.
Le goût des Espagnols pour ces sortes de solennités est si
connu, qu’il ne doit pas être difficile de croire aux féeries religieuses
par lesquelles l’abbaye de San-Lucar célébra la translation du
bienheureux don Juan Belvidéro dans son église. Quelques jours
après la mort de cet illustre seigneur, le miracle de son imparfaite
résurrection s’était si drument conté de village en village, dans un
rayon de plus de cinquante lieues autour de San-Lucar, que ce fut
déjà une comédie que de voir les curieux par les chemins; ils vinrent
de tous côtés, affriandés par un Te Deum chanté aux flambeaux.
L’antique mosquée du couvent de San-Lucar, merveilleux édifice bâti
par les Maures, et dont les voûtes entendaient depuis trois siècles le
nom de Jésus-Christ substitué à celui d’Allah, ne put contenir la
foule accourue pour voir la cérémonie. Pressés comme des fourmis,
des hidalgos en manteaux de velours, et armés de leurs bonnes
épées, se tenaient debout autour des piliers, sans trouver de place
pour plier leurs genoux qui ne se pliaient que là. De ravissantes
paysannes, dont les basquines dessinaient les formes amoureuses,
donnaient le bras à des vieillards en cheveux blancs. Des jeunes
gens aux yeux de feu se trouvaient à côté de vieilles femmes
parées. Puis c’était des couples frémissant d’aise, fiancées
curieuses amenées par leurs bien-aimés; des mariés de la veille;
des enfants se tenant craintifs par la main. Ce monde était là riche
de couleurs, brillant de contrastes, chargé de fleurs, émaillé, faisant
un doux tumulte dans le silence de la nuit. Les larges portes de
l’église s’ouvrirent. Ceux qui, venus trop tard, restèrent en dehors,
voyaient de loin, par les trois portails ouverts, une scène dont les
décorations vaporeuses de nos opéras modernes ne sauraient
donner une faible idée. Des dévotes et des pécheurs, pressés de
gagner les bonnes grâces d’un nouveau saint, allumèrent en son
honneur des milliers de cierges dans cette vaste église, lueurs
intéressées qui donnèrent de magiques aspects au monument. Les
noires arcades, les colonnes et leurs chapiteaux, les chapelles
profondes et brillantes d’or et d’argent, les galeries, les découpures
sarrasines, les traits les plus délicats de cette sculpture délicate, se
dessinaient dans cette lumière surabondante, comme des figures
capricieuses qui se forment dans un brasier rouge. C’était un océan
de feux, dominé, au fond de l’église, par le chœur doré où s’élevait
le maître-autel, dont la gloire eût rivalisé avec celle d’un soleil levant.
En effet, la splendeur des lampes d’or, des candélabres d’argent,
des bannières, des glands, des saints et des ex-voto, pâlissait
devant la châsse où se trouvait don Juan. Le corps de l’impie
étincelait de pierreries, de fleurs, de cristaux, de diamants, d’or, de
plumes aussi blanches que les ailes d’un séraphin, et remplaçait sur
l’autel un tableau du Christ. Autour de lui brillaient des cierges
nombreux qui élançaient dans les airs de flamboyantes ondes. Le
bon abbé de San-Lucar, paré des habits pontificaux, ayant sa mitre
enrichie de pierres précieuses, son rochet, sa crosse d’or, siégeait,
roi du chœur, sur un fauteuil d’un luxe impérial, au milieu de tout son
clergé, composé d’impassibles vieillards en cheveux argentés,
revêtus d’aubes fines, et qui l’entouraient, semblables aux saints
confesseurs que les peintres groupent autour l’Éternel. Le grand-
chantre et les dignitaires du chapitre, décorés des brillants insignes
de leurs vanités ecclésiastiques, allaient et venaient au sein des
nuages formés par l’encens, pareils aux astres qui roulent sur le
firmament. Quand l’heure du triomphe fut venue, les cloches
réveillèrent les échos de la campagne, et cette immense assemblée
jeta vers Dieu le premier cri de louanges par lequel commence le Te
Deum. Cri sublime! C’était des voix pures et légères, des voix de
femmes en extase, mêlées aux voix graves et fortes des hommes,
des milliers de voix si puissantes, que l’orgue n’en domina pas
l’ensemble, malgré le mugissement de ses tuyaux. Seulement les
notes perçantes de la jeune voix des enfants de chœur et les larges
accents de quelques basses-tailles, suscitèrent des idées
gracieuses, peignirent l’enfance et la force, dans ce ravissant
concert de voix humaines confondues en sentiment d’amour.
—Te Deum laudamus!
Du sein de cette cathédrale noire de femmes et d’hommes
agenouillés, ce chant partit semblable à une lumière qui scintille tout
à coup dans la nuit, et le silence fut rompu comme par un coup de
tonnerre. Les voix montèrent avec les nuages d’encens qui jetaient
alors des voiles diaphanes et bleuâtres sur les fantastiques
merveilles de l’architecture. Tout était richesse, parfum, lumière et
mélodie. Au moment où cette musique d’amour et de
reconnaissance s’élança vers l’autel, don Juan, trop poli pour ne pas
remercier, trop spirituel pour ne pas entendre raillerie, répondit par
un rire effrayant, et se prélassa dans sa châsse. Mais le diable
l’ayant fait penser à la chance qu’il courait d’être pris pour un homme
ordinaire, pour un saint, un Boniface, un Pantaléon, il troubla cette
mélodie d’amour par un hurlement auquel se joignirent les mille voix
de l’enfer. La terre bénissait, le ciel maudissait. L’église en trembla
sur ses fondements antiques.
—Te Deum laudamus! disait l’assemblée.
—Allez à tous les diables, bêtes brutes que vous êtes! Dieu,
Dieu! Carajos demonios, animaux, êtes-vous stupides avec votre
Dieu-vieillard!
Et un torrent d’imprécations se déroula comme un ruisseau de
laves brûlantes par une irruption de Vésuve.
—Deus sabaoth, sabaoth! crièrent les chrétiens.
—Vous insultez la majesté de l’enfer! répondit don Juan dont la
bouche grinçait des dents.
Bientôt le bras vivant put passer par-dessus la châsse, et
menaça l’assemblée par des gestes empreints de désespoir et
d’ironie.
—Le saint nous bénit, dirent les vieilles femmes, les enfants et
les fiancés, gens crédules.
Voilà comment nous sommes souvent trompés dans nos
adorations. L’homme supérieur se moque de ceux qui le
complimentent, et complimente quelquefois ceux dont il se moque
au fond du cœur.
Au moment où l’abbé, prosterné devant l’autel, chantait:—Sancte
Johannes, ora pro nobis! Il entendit assez distinctement:—O
coglione.
—Que se passe-t-il donc là-haut? s’écria le sous-prieur en voyant
la châsse remuer.
—Le saint fait le diable, répondit l’abbé.
Alors cette tête vivante se détacha violemment du corps qui ne
vivait plus et tomba sur le crâne jaune de l’officiant.
—Souviens-toi de dona Elvire, cria la tête en dévorant celle de
l’abbé.
Ce dernier jeta un cri affreux qui troubla la cérémonie. Tous les
prêtres accoururent et entourèrent leur souverain.
—Imbécile, dis donc qu’il y a un Dieu? cria la voix au moment où
l’abbé, mordu dans sa cervelle, allait expirer.

Paris, octobre 1830.


MAITRE CORNÉLIUS.

A MONSIEUR LE COMTE GEORGES MNISZECH.

Quelque JALOUX pourrait croire en voyant briller à cette


page un des plus vieux et plus illustres noms sarmates, que
j’essaye, comme en orfévrerie, de rehausser un récent travail
par un bijou ancien, fantaisie à la mode aujourd’hui; mais,
vous et quelques autres aussi, mon cher comte, sauront que
je tâche d’acquitter ici ma dette au Talent, au Souvenir et à
l’Amitié.

En 1479, le jour de la Toussaint, au moment où cette histoire


commença, les vêpres finissaient à la cathédrale de Tours.
L’archevêque Hélie de Bourdeilles se levait de son siége pour
donner lui-même la bénédiction aux fidèles. Le sermon avait duré
longtemps, la nuit était venue pendant l’office et l’obscurité la plus
profonde régnait dans certaines parties de cette belle église dont les
deux tours n’étaient pas encore achevées. Cependant bon nombre
de cierges brûlaient en l’honneur des saints sur les porte-cires
triangulaires destinés à recevoir ces pieuses offrandes dont le mérite
ou la signification n’ont jamais été suffisamment expliqués. Les
luminaires de chaque autel et tous les candélabres du chœur étaient
allumés. Inégalement semées à travers la forêt de piliers et
d’arcades qui soutient les trois nefs de la cathédrale, ces masses de
lumière éclairaient à peine l’immense vaisseau, car en projetant les
fortes ombres des colonnes à travers les galeries de l’édifice, elles y
produisaient mille fantaisies que rehaussaient encore les ténèbres
dans lesquelles étaient ensevelis les cintres, les voussures et les
chapelles latérales, déjà si sombres en plein jour. La foule offrait des
effets non moins pittoresques. Certaines figures se dessinaient si
vaguement dans le clair-obscur, qu’on pouvait les prendre pour des
fantômes; tandis que plusieurs autres, frappées par des lueurs
éparses, attiraient l’attention comme les têtes principales d’un
tableau. Les statues semblaient animées, et les hommes
paraissaient pétrifiés. Çà et là, des yeux brillaient dans le creux des
piliers, la pierre jetait des regards, les marbres parlaient, les voûtes
répétaient des soupirs, l’édifice entier était doué de vie. L’existence
des peuples n’a pas de scènes plus solennelles ni de moments plus
majestueux. A l’homme en masse, il faut toujours du mouvement
pour faire œuvre de poésie; mais à ces heures de religieuses
pensées, où les richesses humaines se marient aux grandeurs
célestes, il se rencontre d’incroyables sublimités dans le silence; il y
a de la terreur dans les genoux pliés et de l’espoir dans les mains
jointes. Le concert de sentiments par lequel toutes les âmes
s’élancent au ciel produit alors un explicable phénomène de
spiritualité. La mystique exaltation des fidèles assemblés réagit sur
chacun d’eux, le plus faible est sans doute porté sur les flots de cet
océan d’amour et de foi. Puissance tout électrique, la prière arrache
ainsi notre nature à elle-même. Cette involontaire union de toutes les
volontés, également prosternées à terre, également élevées aux
cieux, contient sans doute le secret des magiques influences que
possèdent le chant des prêtres et les mélodies de l’orgue, les
parfums et les pompes de l’autel, les voix de la foule et ses
contemplations silencieuses. Aussi ne devons-nous pas être étonnés
de voir au Moyen-âge tant d’amours commencées à l’église après
de longues extases, amours souvent dénouées peu saintement,
mais desquelles les femmes finissaient, comme toujours, par faire
pénitence. Le sentiment religieux avait alors certainement quelques
affinités avec l’amour, il en était ou le principe ou la fin. L’amour était
encore une religion, il avait encore son beau fanatisme, ses
superstitions naïves, ses dévouements sublimes qui sympathisaient
avec ceux du christianisme. Les mœurs de l’époque expliquent
assez bien d’ailleurs l’alliance de la religion et de l’amour. D’abord, la
société ne se trouvait guère en présence que devant les autels.
Seigneurs et vassaux, hommes et femmes n’étaient égaux que là.
Là seulement, les amants pouvaient se voir et correspondre. Enfin,
les fêtes ecclésiastiques composaient le spectacle du temps, l’âme
d’une femme était alors plus vivement remuée au milieu des
cathédrales qu’elle ne l’est aujourd’hui dans un bal ou à l’Opéra. Les
fortes émotions ne ramènent-elles pas toutes les femmes à l’amour?
A force de se mêler à la vie et de la saisir dans tous ses actes, la
religion s’était donc rendue également complice et des vertus et des
vices. La religion avait passé dans la science, dans la politique, dans
l’éloquence, dans les crimes, sur les trônes, dans la peau du malade
et du pauvre; elle était tout. Ces observations demi-savantes
justifieront peut-être la vérité de cette Étude dont certains détails
pourraient effaroucher la morale perfectionnée de notre siècle, un
peu trop collet-monté, comme chacun sait.
Au moment où le chant des prêtres cessa, quand les dernières
notes de l’orgue se mêlèrent aux vibrations de l’amen sorti de la
forte poitrine des chantres, pendant qu’un léger murmure retentissait
encore sous les voûtes lointaines, au moment où l’assemblée
recueillie attendait la bienfaisante parole du prélat, un bourgeois,
pressé de rentrer en son logis, ou craignant pour sa bourse le
tumulte de la sortie, se retira doucement, au risque d’être réputé
mauvais catholique. Un gentilhomme, tapi contre l’un des énormes
piliers qui environnent le chœur et où il était resté comme perdu
dans l’ombre, s’empressa de venir prendre la place abandonnée par
le prudent Tourangeau. En y arrivant, il se cacha promptement le
visage dans les plumes qui ornaient son haut bonnet gris, et
s’agenouilla sur la chaise avec un air de contrition auquel un
inquisiteur aurait pu croire. Après avoir assez attentivement regardé
ce garçon, ses voisins parurent le reconnaître, et se remirent à prier
en laissant échapper certain geste par lequel ils exprimèrent une
même pensée, pensée caustique, railleuse, une médisance muette.
Deux vieilles femmes hochèrent la tête en se jetant un mutuel coup
d’œil qui fouillait l’avenir. La chaise dont s’était emparé le jeune
homme se trouvait près d’une chapelle pratiquée entre deux piliers,
et fermée par une grille de fer. Le chapitre louait alors, moyennant
d’assez fortes redevances, à certaines familles seigneuriales ou
même à de riches bourgeois, le droit d’assister aux offices,
exclusivement, eux et leurs gens, dans les chapelles latérales,
situées le long des deux petites nefs qui tournent autour de la
cathédrale. Cette simonie se pratique encore aujourd’hui. Une
femme avait sa chapelle à l’église, comme de nos jours elle prend
une loge aux Italiens. Les locataires de ces places privilégiées
avaient en outre la charge d’entretenir l’autel qui leur était concédé.
Chacun mettait donc son amour-propre à décorer somptueusement
le sien, vanité dont s’accommodait assez bien l’église. Dans cette
chapelle et près de la grille, une jeune dame était agenouillée sur un
beau carreau de velours rouge à glands d’or, précisément auprès de
la place précédemment occupée par le bourgeois. Une lampe
d’argent vermeil suspendue à la voûte de la chapelle, devant un
autel magnifiquement orné, jetait sa pâle lumière sur le livre
d’Heures que tenait la dame. Ce livre trembla violemment dans ses
mains quand le jeune homme vint près d’elle.
—Amen!
A ce répons, chanté d’une voix douce, mais cruellement agitée,
et qui heureusement se confondit dans la clameur générale, elle
ajouta vivement et à voix basse:—Vous me perdez.
Cette parole fut dite avec un accent d’innocence auquel devait
obéir un homme délicat, elle allait au cœur et le perçait; mais
l’inconnu, sans doute emporté par un de ces paroxysmes de passion
qui étouffent la conscience, resta sur sa chaise et releva légèrement
la tête, pour jeter un coup d’œil dans la chapelle.
—Il dort! répondit-il d’une voix si bien assourdie que cette
réponse dut être entendue par la jeune femme comme un son par
l’écho.
La dame pâlit, son regard furtif quitta pour un moment le vélin du
livre et se dirigea sur un vieillard que le jeune homme avait regardé.
Quelle terrible complicité ne se trouvait-il pas dans cette œillade?
Lorsque la jeune femme eut examiné ce vieillard, elle respira
fortement et leva son beau front orné d’une pierre précieuse vers un
tableau où la Vierge était peinte; ce simple mouvement, cette
attitude, le regard mouillé disaient toute sa vie avec une imprudente
naïveté; perverse, elle eût été dissimulée. Le personnage qui faisait
tant de peur aux deux amants était un petit vieillard, bossu, presque
chauve, de physionomie farouche, ayant une large barbe d’un blanc
sale et taillée en éventail; la croix de Saint-Michel brillait sur sa
poitrine; ses mains rudes, fortes, sillonnées de poils gris, et que
d’abord il avait sans doute jointes, s’étaient légèrement désunies
pendant le sommeil auquel il se laissait si imprudemment aller. Sa
main droite semblait près de tomber sur sa dague, dont la garde
formait une espèce de grosse coquille en fer sculpté; par la manière
dont il avait rangé son arme, le pommeau se trouvait sous sa main;
si, par malheur, elle venait à toucher le fer, nul doute qu’il ne
s’éveillât aussitôt, et ne jetât un regard sur sa femme. Ses lèvres
sardoniques, son menton pointu, capricieusement relevé,
présentaient les signes caractéristiques d’un malicieux esprit, d’une
sagacité froidement cruelle qui devait lui permettre de tout deviner,
parce qu’il savait tout supposer. Son front jaune était plissé comme
celui des hommes habitués à ne rien croire, à tout peser, et qui,
semblables aux avares faisant trébucher leurs pièces d’or, cherchent
le sens et la valeur exacte des actions humaines. Il avait une
charpente osseuse et solide, paraissait être nerveux, partant
irritable; bref, vous eussiez dit d’un ogre manqué. Donc, au réveil de
ce terrible seigneur, un inévitable danger attendait la jeune dame. Ce
mari jaloux ne manquerait pas de reconnaître la différence qui
existait entre le vieux bourgeois duquel il n’avait pris aucun
ombrage, et le nouveau venu, courtisan jeune, svelte, élégant.
—Libera nos a malo, dit-elle en essayant de faire comprendre
ses craintes au cruel jeune homme.
Celui-ci leva la tête vers elle et la regarda. Il avait des pleurs
dans les yeux, pleurs d’amour ou de désespoir. A cette vue la dame
tressaillit, elle se perdit. Tous deux résistaient sans doute depuis
longtemps, et ne pouvaient peut-être plus résister à un amour grandi
de jour en jour par d’invincibles obstacles, couvé par la terreur,
fortifié par la jeunesse. Cette femme était médiocrement belle, mais
son teint pâle accusait de secrètes souffrances qui la rendaient
intéressante. Elle avait d’ailleurs les formes distinguées et les plus
beaux cheveux du monde. Gardée par un tigre, elle risquait peut-
être sa vie en disant un mot, en se laissant presser la main, en
accueillant un regard. Si jamais amour n’avait été plus profondément
enseveli dans deux cœurs, plus délicieusement savouré, jamais
aussi passion ne devait être plus périlleuse. Il était facile de deviner
que, pour ces deux êtres, l’air, les sons, le bruit des pas sur les
dalles, les choses les plus indifférentes aux autres hommes, offraient
des qualités sensibles, des propriétés particulières qu’ils devinaient.
Peut-être l’amour leur faisait-il trouver des truchements fidèles
jusque dans les mains glacées du vieux prêtre auquel ils allaient dire
leurs péchés, ou desquelles ils recevaient une hostie en approchant
de la sainte table. Amour profond, amour entaillé dans l’âme comme
dans le corps une cicatrice qu’il faut garder durant toute la vie.
Quand ces deux jeunes gens se regardèrent, la femme sembla dire
à son amant:—Périssons, mais aimons-nous. Et le cavalier parut lui
répondre:—Nous nous aimerons, et ne périrons pas. Alors, par un
mouvement de tête plein de mélancolie, elle lui montra une vieille
duègne et deux pages. La duègne dormait. Les deux pages étaient
jeunes, et paraissaient assez insouciants de ce qui pouvait arriver de
bien ou de mal à leur maître.
—Ne vous effrayez pas à la sortie, et laissez-vous faire.
A peine le gentilhomme eut-il dit ces paroles à voix basse, que la
main du vieux seigneur coula sur le pommeau de son épée. En
sentant la froideur du fer, le vieillard s’éveilla soudain; ses yeux
jaunes se fixèrent aussitôt sur sa femme. Par un privilége assez
rarement accordé même aux hommes de génie, il retrouva son
intelligence aussi nette et ses idées aussi claires que s’il n’avait pas
sommeillé. C’était un jaloux. Si le jeune cavalier donnait un œil à sa
maîtresse, de l’autre il guignait le mari; il se leva lestement, et
s’effaça derrière le pilier au moment où la main du vieillard voulut se
mouvoir; puis il disparut, léger comme un oiseau. La dame baissa
promptement les yeux, feignit de lire et tâcha de paraître calme;
mais elle ne pouvait empêcher ni son visage de rougir, ni son cœur
de battre avec une violence inusitée. Le vieux seigneur entendit le
bruit des pulsations profondes qui retentissaient dans la chapelle, et
remarqua l’incarnat extraordinaire répandu sur les joues, sur le front,
sur les paupières de sa femme; il regarda prudemment autour de lui;
mais, ne voyant personne dont il dût se défier:—A quoi pensez-vous
donc, ma mie? lui dit-il.
—L’odeur de l’encens me fait mal, répondit-elle.
—Il est donc mauvais d’aujourd’hui, répliqua le seigneur.
Malgré cette observation, le rusé vieillard parut croire à cette
défaite; mais il soupçonna quelque trahison secrète et résolut de
veiller encore plus attentivement sur son trésor. La bénédiction était
donnée. Sans attendre la fin du secula seculorum, la foule se
précipitait comme un torrent vers les portes de l’église. Suivant son
habitude, le seigneur attendit prudemment que l’empressement
général fût calmé, puis il sortit en faisant marcher devant lui la
duègne et le plus jeune page qui portait un falot; il donna le bras à
sa femme, et se fit suivre par l’autre page. Au moment où le vieux
seigneur allait atteindre la porte latérale ouverte dans la partie
orientale du cloître et par laquelle il avait coutume de sortir, un flot de
monde se détacha de la foule qui obstruait le grand portail, reflua
vers la petite nef où il se trouvait avec son monde, et cette masse
compacte l’empêcha de retourner sur ses pas. Le seigneur et sa
femme furent alors poussés au dehors par la puissante pression de
cette multitude. Le mari tâcha de passer le premier en tirant
fortement la dame par le bras; mais, en ce moment, il fut entraîné
vigoureusement dans la rue, et sa femme lui fut arrachée par un
étranger. Le terrible bossu comprit soudain qu’il était tombé dans
une embûche préparée de longue main. Se repentant d’avoir dormi
si longtemps, il rassembla toute sa force; d’une main ressaisit sa
femme par la manche de sa robe, et de l’autre essaya de se
cramponner à la porte. Mais l’ardeur de l’amour l’emporta sur la rage
de la jalousie. Le jeune gentilhomme prit sa maîtresse par la taille,
l’enleva si rapidement et avec une telle force de désespoir, que
l’étoffe de soie et d’or, le brocart et les baleines, se déchirèrent
bruyamment. La manche resta seule au mari. Un rugissement de
lion couvrit aussitôt les cris poussés par la multitude, et l’on entendit
bientôt une voix terrible hurlant ces mots:—A moi, Poitiers! Au
portail, les gens du comte de Saint-Vallier! Au secours! ici!
Et le comte Aymar de Poitiers, sire de Saint-Vallier, tenta de tirer
son épée et de se faire faire place; mais il se vit environné, pressé
par trente ou quarante gentilshommes qu’il était dangereux de
blesser. Plusieurs d’entre eux, qui étaient du plus haut rang, lui
répondirent par des quolibets en l’entraînant dans le passage du
cloître. Avec la rapidité de l’éclair, le ravisseur avait emmené la
comtesse dans une chapelle ouverte où il l’assit derrière un
confessionnal, sur un banc de bois. A la lueur des cierges qui
brûlaient devant l’image du saint auquel cette chapelle était dédiée,
ils se regardèrent un moment en silence, en se pressant les mains,
étonnés l’un et l’autre de leur audace. La comtesse n’eut pas le cruel
courage de reprocher au jeune homme la hardiesse à laquelle ils
devaient ce périlleux, ce premier instant de bonheur.
—Voulez-vous fuir avec moi dans les États voisins? lui dit
vivement le gentilhomme. J’ai près d’ici deux genets d’Angleterre
capables de faire trente lieues d’une seule traite.
—Eh! s’écria-t-elle doucement, en quel lieu du monde trouverez-
vous un asile pour une fille du roi Louis Onze?
—C’est vrai, répondit le jeune homme stupéfait de n’avoir pas
prévu cette difficulté.
—Pourquoi donc m’avez-vous arrachée à mon mari? demanda-t-
elle avec une sorte de terreur.
—Hélas! reprit le cavalier, je n’ai pas compté sur le trouble où je
suis en me trouvant près de vous, en vous entendant me parler. J’ai
conçu deux ou trois plans, et maintenant tout me semble accompli,
puisque je vous vois.
—Mais je suis perdue, dit la comtesse.
—Nous sommes sauvés, répliqua le gentilhomme avec l’aveugle
enthousiasme de l’amour. Écoutez-moi bien.
—Ceci me coûtera la vie, reprit-elle en laissant couler les larmes
qui roulaient dans ses yeux. Le comte me tuera ce soir peut-être!
Mais, allez chez le roi, racontez-lui les tourments que depuis cinq
ans sa fille a endurés. Il m’aimait bien quand j’étais petite, et
m’appelait en riant: Marie-pleine-de-grâce, parce que j’étais laide.
Ah! s’il savait à quel homme il m’a donnée, il se mettrait dans une
terrible colère. Je n’ai pas osé me plaindre, par pitié pour le comte.
D’ailleurs, comment ma voix parviendrait-elle au roi? Mon
confesseur lui-même est un espion de Saint-Vallier. Aussi me suis-je
prêtée à ce coupable enlèvement, dans l’espoir de conquérir un
défenseur. Mais puis-je me fier à...—Oh! dit-elle en pâlissant et
s’interrompant, voici le page.
La pauvre comtesse se fit comme un voile avec ses mains pour
se cacher la figure.
—Ne craignez rien, reprit le jeune seigneur, il est gagné! Vous
pouvez vous servir de lui en toute assurance, il m’appartient. Quand
le comte viendra vous chercher, il nous préviendra de son arrivée.—
Dans ce confessionnal, ajouta-t-il à voix basse, est un chanoine de
mes amis qui sera censé vous avoir retirée de la bagarre, et mise
sous sa protection dans cette chapelle. Ainsi, tout est prévu pour
tromper Saint-Vallier.
A ces mots, les larmes de la comtesse se séchèrent, mais une
expression de tristesse vint rembrunir son front.
—On ne le trompe pas! dit-elle. Ce soir, il saura tout, prévenez
ses coups! Allez au Plessis, voyez le roi, dites-lui que... Elle hésita.
Mais quelque souvenir lui ayant donné le courage d’avouer les
secrets du mariage:—Eh! bien, oui, reprit-elle, dites-lui que, pour se
rendre maître de moi, le comte me fait saigner aux deux bras, et
m’épuise. Dites qu’il m’a traînée par les cheveux, dites que je suis
prisonnière, dites que...
Son cœur se gonfla, les sanglots expirèrent dans son gosier,
quelques larmes tombèrent de ses yeux; et dans son agitation, elle
se laissa baiser les mains par le jeune homme auquel il échappait
des mots sans suite.
—Personne ne peut parler au roi, pauvre petite! J’ai beau être le
neveu du grand-maître des arbalétriers, je n’entrerai pas ce soir au
Plessis. Ma chère dame, ma belle souveraine! Mon Dieu, a-t-elle
souffert! Marie, laissez-moi vous dire deux mots, ou nous sommes
perdus.
—Que devenir? dit-elle.
La comtesse aperçut à la noire muraille un tableau de la Vierge,
sur lequel tombait la lueur de la lampe, et s’écria:—Sainte mère de
Dieu, conseillez-nous!
—Ce soir, reprit le jeune seigneur, je serai chez vous.
—Et comment? demanda-t-elle naïvement.
Ils étaient dans un si grand péril, que leurs plus douces paroles
semblaient dénuées d’amour.
—Ce soir, reprit le gentilhomme, je vais aller m’offrir en qualité
d’apprenti à maître Cornélius, l’argentier du roi. J’ai su me procurer
une lettre de recommandation qui me fera recevoir. Son logis est
voisin du vôtre. Une fois sous le toit de ce vieux ladre, à l’aide d’une
échelle de soie je saurai trouver le chemin de votre appartement.
—Oh! dit-elle pétrifiée d’horreur, si vous m’aimez, n’allez pas
chez maître Cornélius!
—Ah! s’écria-t-il en la serrant contre son cœur avec toute la force
que l’on se sent à son âge, vous m’aimez donc!
—Oui, dit-elle. N’êtes-vous pas mon espérance? Vous êtes
gentilhomme, je vous confie mon honneur!—D’ailleurs, reprit-elle en
le regardant avec dignité, je suis trop malheureuse pour que vous
trahissiez ma foi. Mais à quoi bon tout ceci? Allez, laissez-moi mourir
plutôt que d’entrer chez Cornélius! Ne savez-vous pas que tous ses
apprentis...
—Ont été pendus, reprit en riant le gentilhomme. Croyez-vous
que ses trésors me tentent?
—Oh! n’y allez pas, vous y seriez victime de quelque sorcellerie.
—Je ne saurais trop payer le bonheur de vous servir, répondit-il
en lui lançant un regard de feu qui lui fit baisser les yeux.
—Et mon mari? dit-elle.
—Voici qui l’endormira, reprit le jeune homme en tirant de sa
ceinture un petit flacon.
—Pas pour toujours? demanda la comtesse en tremblant.
Pour toute réponse, le gentilhomme fit un geste d’horreur.
—Je l’aurais déjà défié en combat singulier, s’il n’était pas si
vieux, ajouta-t-il. Dieu me garde jamais de vous en défaire en lui
donnant le boucon!
—Pardon, dit la comtesse en rougissant, je suis cruellement
punie de mes péchés. Dans un moment de désespoir, j’ai voulu tuer
le comte, je craignais que vous n’eussiez eu le même désir. Ma
douleur est grande de n’avoir point encore pu me confesser de cette
mauvaise pensée; mais j’ai eu peur que mon idée ne lui fût
découverte, qu’il ne s’en vengeât.—Je vous fais honte, reprit-elle,
offensée du silence que gardait le jeune homme. J’ai mérité ce
blâme.
Elle brisa le flacon en le jetant à terre avec violence.
—Ne venez pas, s’écria-t-elle, le comte a le sommeil léger. Mon
devoir est d’attendre secours du ciel. Ainsi ferai-je!
Elle voulut sortir.
—Ah! s’écria le gentilhomme, ordonnez, je le tuerai, madame.
Vous me verrez ce soir.
—J’ai été sage de dissiper cette drogue, répliqua-t-elle d’une voix
éteinte par le plaisir de se voir si ardemment aimée. La peur de
réveiller mon mari nous sauvera de nous-mêmes.
—Je vous fiance ma vie, dit le jeune homme en lui serrant la
main.
—Si le roi veut, le pape saura casser mon mariage. Nous serions
unis, alors, reprit-elle en lui lançant un regard plein de délicieuses
espérances.
—Voici mon seigneur! s’écria le page en accourant.
Aussitôt le gentilhomme, étonné du peu de temps pendant lequel
il était resté près de sa maîtresse, et surpris de la célérité du comte,
prit un baiser que sa maîtresse ne sut pas refuser.
—A ce soir! lui dit-il en s’esquivant de la chapelle.
A la faveur de l’obscurité, l’amoureux gagna le grand portail en
s’évadant de pilier en pilier, dans la longue trace d’ombre que
chaque grosse colonne projetait à travers l’église. Un vieux chanoine
sortit tout à coup du confessionnal, vint se mettre auprès de la
comtesse, et ferma doucement la grille devant laquelle le page se
promena gravement avec une assurance de meurtrier. De vives
clartés annoncèrent le comte. Accompagné de quelques amis et de
gens qui portaient des torches, il tenait à la main son épée nue. Ses
yeux sombres semblaient percer les ténèbres profondes et visiter les
coins les plus obscurs de la cathédrale.
—Monseigneur, madame est là, lui dit le page en allant au devant
de lui.
Le sire de Saint-Vallier trouva sa femme agenouillée aux pieds
de l’autel, et le chanoine debout, disant son bréviaire. A ce
spectacle, il secoua vivement la grille, comme pour donner pâture à
sa rage.
—Que voulez-vous, une épée nue à la main dans l’église?
demanda le chanoine.
—Mon père, monsieur est mon mari, répondit la comtesse.
Le prêtre tira la clef de sa manche, et ouvrit la chapelle. Le comte
jeta presque malgré lui des regards autour du confessionnal, y entra;
puis, il se mit à écouter le silence de la cathédrale.
—Monsieur, lui dit sa femme, vous devez des remercîments à ce
vénérable chanoine qui m’a retirée ici.
Le sire de Saint-Vallier pâlit de colère, n’osa regarder ses amis,
venus là plus pour rire de lui que pour l’assister, et repartit
brièvement:—Merci Dieu, mon père, je trouverai moyen de vous
récompenser!
Il prit sa femme par le bras, et sans la laisser achever sa
révérence au chanoine, il fit un signe à ses gens, et sortit de l’église
sans dire un mot à ceux qui l’avaient accompagné. Son silence avait
quelque chose de farouche. Impatient d’être au logis, préoccupé des
moyens de découvrir la vérité, il se mit en marche à travers les rues
tortueuses qui séparaient alors la Cathédrale du portail de la
Chancellerie, où s’élevait le bel hôtel, alors récemment bâti par le
chancelier Juvénal des Ursins, sur l’emplacement d’une ancienne
fortification que Charles VII avait donnée à ce fidèle serviteur en
récompense de ses glorieux labeurs. Là commençait une rue
nommée depuis lors de la Scéellerie, en mémoire des sceaux qui y
furent longtemps. Elle joignait le vieux Tours au bourg de
Châteauneuf, où se trouvait la célèbre abbaye de Saint-Martin, dont
tant de rois furent simples chanoines. Depuis cent ans, et après de
longues discussions, ce bourg avait été réuni à la ville. Beaucoup de
rues adjacentes à celle de la Scéellerie, et qui forment aujourd’hui le
centre du Tours moderne, étaient déjà construites; mais les plus
beaux hôtels, et notamment celui du trésorier Xancoings, maison qui
subsiste encore dans la rue du Commerce, étaient situés dans la
commune de Châteauneuf. Ce fut par là que les porte-flambeaux du
sire de Saint-Vallier le guidèrent vers la partie du bourg qui avoisinait
la Loire; il suivait machinalement ses gens en lançant de temps en
temps un coup d’œil sombre à sa femme et au page, pour
surprendre entre eux un regard d’intelligence qui jetât quelque
lumière sur cette rencontre désespérante. Enfin, le comte arriva
dans la rue du Mûrier, où son logis était situé. Lorsque son cortége
fut entré, que la lourde porte fut fermée, un profond silence régna
dans cette rue étroite où logeaient alors quelques seigneurs, car ce
nouveau quartier de la ville avoisinait le Plessis, séjour habituel du
roi, chez qui les courtisans pouvaient aller en un moment. La
dernière maison de cette rue était aussi la dernière de la ville, et
appartenait à maître Cornélius Hoogworst, vieux négociant
brabançon, à qui le roi Louis XI accordait sa confiance dans les
transactions financières que sa politique astucieuse l’obligeait à faire
au dehors du royaume. Par des raisons favorables à la tyrannie qu’il
exerçait sur sa femme, le comte de Saint-Vallier s’était jadis établi
dans un hôtel contigu au logis de ce maître Cornélius. La
topographie des lieux expliquera les bénéfices que cette situation
pouvait offrir à un jaloux. La maison du comte, nommée l’hôtel de
Poitiers, avait un jardin bordé au nord par le mur et le fossé qui
servaient d’enceinte à l’ancien bourg de Châteauneuf, et le long

You might also like