Pgsal

Pablo Galindo Salgado

pablo.occupation: works on the CPython parser and error messages; writes profilers and debuggers for Python; co-hosts the core.py podcast.

SCHWARZSCHILD · i --.-° · φ ---.-° · ------ RAYS/FRAME · -- FPS

Point at the image to trace one ray. Click to launch rays from that point.

§ I

About

Pixel portrait of Pablo wearing an ornate dark mask
Traceback (most recent call last):
  File "~/granada/phd/geodesics.py", line 2014, in regularize
    orbit = mcgehee(spherically_symmetric_spacetime)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "~/cpython/Doc/howto/logging-cookbook.rst", line 2017, in first_pr
    fix(ZeroMQSocketHandler)  # bpo-31294
        ^^^^^^^^^^^^^^^^^^^
  File "~/cpython/Parser/parser.c", line 2020, in replace_the_parser
    parser = PEG(grammar)  # PEP 617
             ^^^^^^^^^^^^
  File "~/cpython/Python/pythonrun.c", line 2021, in print_exception
    print('Did you mean: ...?')
          ^^^^^^^^^^^^^^^^^^^^
  File "~/cpython/Python/sysmodule.c", line 2025, in sys_remote_exec
    sys.remote_exec(pid, script)  # PEP 768
                    ^^^

Most days I work on the Python interpreter. I work on the parts you see when something goes wrong: the parser, the error messages and the tracebacks. I also work on the code that lets debuggers and profilers look inside a running process.

I came to software from theoretical physics. My PhD was on general relativity and black holes. I learned Python to glue together C simulation code. Later, Python itself became more interesting to me than the simulations.

I have been a CPython core developer since 2018. I have been on the Python Steering Council every term since 2021. I was the release manager for Python 3.10 and 3.11.

I work on the Python team at Hudson River Trading, in London.

Core developer
since 2018
Steering Council
2021 to 2026
Release manager
3.10 and 3.11
PSF Fellow
since 2019
Works at
Hudson River Trading
Based in
London
§ II python/cpython

CPython

I became a CPython core developer in June 2018. This section lists my roles, my PEPs and my changes to each release since 3.8.

Numbers

years as a core developer
8
merged pull requests
1,121
PEPs as author or co-author
15
all-time contributor rank
#29

Counts from GitHub, queried 24 September 2026.

Merged pull requests

One square is 20 pull requests, by year opened. 2026 is not complete.

PEPs

My name is on 15 PEPs. Eleven are final. Two are the release schedules for 3.10 and 3.11. One is rejected and one is withdrawn.

  1. PEP 617 3.9

    New PEG parser for CPython

    Guido, Lysandros and I replaced the old LL(1) parser with a PEG parser.

  2. PEP 657 3.11

    Include Fine Grained Error Locations in Tracebacks

    Tracebacks mark the exact expression that failed with ^^^^^.

  3. PEP 701 3.12

    Syntactic formalization of f-strings

    f-strings are part of the grammar. You can reuse quotes inside them.

  4. PEP 768 3.14

    Safe external debugger interface for CPython

    Debuggers can attach to a running process. pdb -p PID uses it.

  5. PEP 799 3.15

    A dedicated profiling package for organizing Python profiling tools

    A new profiling package. It includes Tachyon, a sampling profiler.

  6. PEP 810 3.15

    Explicit lazy imports

    lazy import json loads the module only when you first use it.

  1. 570 Python Positional-Only Parameters Final
  2. 619 Python 3.10 Release Schedule Active
  3. 664 Python 3.11 Release Schedule Active
  4. 679 New assert statement syntax with parentheses Rejected
  5. 758 Allow except and except* expressions without parentheses Final
  6. 760 No More Bare Excepts Withdrawn
  7. 762 REPL-acing the default REPL Final
  8. 831 Frame Pointers Everywhere: Enabling System-Level Observability for Python Final
  9. 8001 Python Governance Voting Process Final

Changes by release

These are the changes I wrote or co-wrote in each release. Each one links to What's New and to the issue.

  1. Python 3.15 Tachyon and the profiling package / Explicit lazy imports / Frame pointers by default / JIT unwind info for GDB and backtrace in development
    • Tachyon and the profiling package

      Tachyon (profiling.sampling) is a high-frequency sampling profiler. It can attach to running processes. cProfile moves to profiling.tracing. László Kiss Kollár and I built Tachyon.

      PEP 799 What's New 3.15docsgh-135953

    • Explicit lazy imports

      The new lazy import statement. Dino Viehland and I implemented it.

      PEP 810 What's New 3.15gh-142349

    • Frame pointers by default

      CPython builds with frame pointers by default. Native profilers and debuggers can then walk through Python frames.

      PEP 831 What's New 3.15gh-149201

    • JIT unwind info for GDB and backtrace

      Native debuggers can unwind through JIT-compiled frames. Before, they stopped at the generated code. Diego Russo and I did this work.

      What's New 3.15gh-146071

  2. Python 3.14 Remote debugging: sys.remote_exec and pdb -p / asyncio introspection: python -m asyncio ps and pstree / Template strings / Bracketless except 2025
    • Remote debugging: sys.remote_exec and pdb -p

      sys.remote_exec() and python -m pdb -p PID let you attach to a live Python process and debug it without restarting.

      PEP 768 What's New 3.14gh-131591

    • asyncio introspection: python -m asyncio ps and pstree

      Run them against a running process to see which tasks wait on which. I also added asyncio.capture_call_graph() and print_call_graph().

      What's New 3.14gh-91048

    • Template strings

      I was one of the people who implemented t-strings (PEP 750). I worked mainly on the parser.

      What's New 3.14gh-132661

    • Bracketless except

      You can write except A, B: without parentheses.

      PEP 758 What's New 3.14gh-131831

  3. Python 3.13 A new interactive REPL, and colored tracebacks / PyRefTracer C API 2024
    • A new interactive REPL, and colored tracebacks

      Łukasz, Lysandros and I built the new default REPL, based on the PyPy REPL. I also made tracebacks colored by default.

      PEP 762 What's New 3.13gh-111201gh-112730

    • PyRefTracer C API

      New C API hooks that report when objects are created and destroyed. Memory profilers can use them.

      What's New 3.13gh-93502

  4. Python 3.12 f-strings in the grammar / Linux perf profiler support / threading.settrace_all_threads and setprofile_all_threads 2023
    • f-strings in the grammar

      f-strings are now part of the grammar. The tokenize module also became up to 64% faster.

      PEP 701 What's New 3.12gh-102856

    • Linux perf profiler support

      I designed and wrote support for the Linux perf profiler (-X perf). With it, Python function names show up in native profiles. 3.13 added -X perf_jit, which works without frame pointers.

      docsgh-96123gh-118518

    • threading.settrace_all_threads and setprofile_all_threads

      You can now install a tracer or profiler on every thread at once.

      What's New 3.12gh-93503

  5. Python 3.11 Fine-grained error locations in tracebacks / Inlined Python-to-Python calls 2022 RM
    • Fine-grained error locations in tracebacks

      Tracebacks underline the exact expression that failed. Before 3.11, they showed only the line.

      PEP 657 What's New 3.11bpo-43950

    • Inlined Python-to-Python calls

      Mark Shannon and I made Python-to-Python calls stop using the C stack. Simple recursive code became about 1.7x faster.

      What's New 3.11bpo-45256

  6. Python 3.10 Better error messages and “Did you mean” suggestions / Parenthesized context managers / LOAD_ATTR opcode cache 2021 RM
    • Better error messages and “Did you mean” suggestions

      In 3.10 I rewrote many SyntaxErrors, for example "expected ':'", "Perhaps you forgot a comma?" and unclosed brackets. I also added "Did you mean" suggestions for NameError and AttributeError. I improve them in every release. 3.12 added import suggestions. 3.14 added keyword typo suggestions like "Did you mean 'while'?".

      What's New 3.10What's New 3.12What's New 3.14bpo-38530

    • Parenthesized context managers

      With the new parser, multi-line with (a() as x, b() as y): became official syntax.

      What's New 3.10bpo-12782

    • LOAD_ATTR opcode cache

      Yury Selivanov and I added a per-opcode cache. It made attribute access about 36% faster (44% for slots).

      What's New 3.10bpo-42093

  7. Python 3.9 The PEG parser / graphlib and ast.unparse 2020
    • The PEG parser

      The new PEG parser became the default in 3.9. We deleted the old LL(1) parser in 3.10.

      PEP 617 What's New 3.9bpo-40334

    • graphlib and ast.unparse

      I wrote the graphlib module (topological sorting) with Tim Peters and Larry Hastings. I wrote ast.unparse() with Batuhan Taskaya.

      What's New 3.9bpo-17005bpo-38870

  8. Python 3.8 Positional-only parameters / math.prod and smaller changes / Garbage collector work 2019
    • Positional-only parameters

      I implemented the / syntax for positional-only parameters.

      PEP 570 What's New 3.8bpo-36540

    • math.prod and smaller changes

      I added math.prod() and gc.get_objects(generation=...). I also helped make namedtuple field lookups and class variable writes faster.

      What's New 3.8bpo-35606bpo-36016

    • Garbage collector work

      I worked on the garbage collector from 3.8 to 3.12. 3.8 got gc.get_objects(generation). 3.9 got correct handling of resurrected objects and gc.is_finalized. 3.10 got GC audit hooks. In 3.12, GC runs moved from object allocation to the eval breaker.

      What's New 3.9bpo-38379gh-97922

python3.11

$ python3.11 area.py
Traceback (most recent call last):
  File "/tmp/area.py", line 4, in <module>
    area({"width": 4, "height": None})
  File "/tmp/area.py", line 2, in area
    return shape["width"] * shape["height"]
           ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
The tildes mark the operands. The carets mark the operator that failed.
§ III profilers and debuggers

Tools

I build tools that inspect running Python processes. They read the memory, the call stacks and the native frames of the process.

15.2k stars on GitHub Python · C++

Memray

Co-creator, with Matt Wozniski at Bloomberg

A memory profiler for Python. It tracks every allocation in Python code, in native extension modules and in the interpreter.

1.2k stars on GitHub C++ · Python

PyStack

Co-creator, with Matt Wozniski at Bloomberg

Prints the stack of a running Python process or a core dump. It shows the Python frames and the native frames together.

202 stars on GitHub Python

pegen

Co-author, PEP 617

The PEG parser generator that builds the CPython parser. This standalone version works with your own grammars.

python -m pegen my_grammar.gram -o parser.py

Other experiments

Stars as of Sep 2026

  • python-horror-show 368 stars

    Strange Python snippets, with an explanation of how each one works.

    Python
  • slowlify 25 stars

    Makes a fast laptop behave like an overloaded CI runner, to reproduce failures that only happen in CI.

    Shell
  • memory.python.org 19 stars

    Memory benchmarks for CPython, tracked across commits and build configurations.

    Python
  • stackpulse 6 stars

    A Rust library for Linux profilers on perf_event. It resolves native, Python, JIT and kernel frames.

    Rust
  • cpython-unwind 6 stars

    Unwinds the native stack with GNU backtrace, libunwind and libdw, so you can compare them.

    C
  • gdb-emoji 5 stars

    Shows pointers as emoji in GDB, so you can tell them apart.

    Python
  • ghost_unwind 3 stars

    Shadow-stack unwinding. It is a drop-in replacement for unw_backtrace().

    C++
  • gsym-rs 2 stars

    A Rust reader, writer and ELF/DWARF converter for the LLVM GSYM symbol format.

    Rust
Show all 14 Show fewer
  • libunwinder 1 stars

    A native stack unwinder for profilers, built on a vendored libunwind.

    Rust
  • symbol_renamer 1 stars

    Renames dynamic symbols in extension modules and their shared libraries to fix symbol clashes.

    Python
  • hexforge

    patchelf, rewritten as a compiler pass. It lifts the ELF file into a typed IR, then checks and changes it.

    Rust
  • unrepair

    Undoes part of auditwheel repair. It points an extension module back at the system library.

    Rust
  • fenix

    Writes a core dump for the debugger when a program stops on an uncaught exception. It has no cost until then.

    Python
  • ShadowEngine

    A CUDA raytracer for the Kerr spacetime. It shows how light moves around a spinning black hole.

    CUDA
§ IV podcast

core.py

core.py is a podcast about CPython internals. Łukasz Langa and I host it. We talk about what changes in each release and why.

31 episodes, 49 hours, since 2023

core.py cover art: three snakes knotted around the words CORE PY

Latest · No. 30

Episode 30: Live from EuroPython, an Interview with Guido van Rossum

A short live episode from EuroPython 2026. We interview Guido van Rossum about the Grail web browser, Rietveld, aesthetics in code, and music.

0:00 / 42:47

All episodes

  1. Episode 30 Live from EuroPython, an Interview with Guido van Rossum
  2. Episode 29 Is CPython developed with AI now?
  3. Episode 28 2025 In Review
  4. Episode 27 Calling Things, Part 1
  5. Episode 26.2 CPython Sprint Week in Cambridge UK, Part 2
  6. Episode 26.1 CPython Sprint Week in Cambridge UK, Part 1
  7. Episode 25 A Python That Never Was
  8. Episode 24 The Megahertz
Show all 31 Show fewer
  1. Episode 23 PyCon US 2025 Recap
  2. Episode 22 Beta Frenzy
  3. Episode 21 A Garbage Episode
  4. Episode 20 Remote Code Execution By Design
  5. Episode 19 Async hacks, unicorns and velociraptors
  6. Episode 18 Reference Counting
  7. Episode 17 Argparse, JIT, and balloons with Savannah Ostrowski
  8. Episode 16 Memory Allocation
  9. Episode 15 Core sprint at Meta
  10. Episode 14 Integration Events
  11. Episode 13 A Legit Episode
  12. Episode 12 WTF Python
  13. Episode 11 Live from PyCon 2024
  14. Episode 10 The Interactive REPL
  15. Episode 9 Py Day with Emily Morehouse-Valcarcel
  16. Episode 8 The New Parser
  17. Episode 7 The Old Parser
  18. Episode 6 An Exceptional Episode
  19. Episode 5 Cinder with Carl Meyer
  20. Episode 4 Frame Evaluation
  21. Episode 3 Imports, frozen modules, Python news
  22. Episode 2 PEP 703: Removing the GIL
  23. Episode 1 Core Sprint in Brno & Python 3.13.0 alpha 1
§ V conferences

Talks

I have given 60 talks since 2015, in English and Spanish. Most of them are about CPython internals.

Selected keynotes

Keynote · PyCon US 2026 · · ES

Horizonte de sucesos / Event Horizon

The first keynote in Spanish at PyCon US, with live English captions and audio. It is about how a large group of people builds Python, and what AI-generated contributions mean for the core team.

  1. Core.py live with Guido van Rossum

    EuroPython 2026

  2. Parsers, Threads and Labyrinths

    PyCon Greece 2025

  3. Um Siri fazendo barra

    PyCon Portugal 2025

  4. Nobody expects the Spanish inquisition

    EuroPython 2021

  5. Inside Python: through the eyes of a core developer

    PyConES 2019

Every talk

2015 2026

60 talks

2026

  1. EuroPython 2026

    Lazy imports and the art of interpreter procrastination

    How PEP 810 brought explicit lazy imports to Python 3.15. We follow them from the bytecode to the proxy objects that load a module on first use. With Noah Kim.

    Play “Lazy imports and the art of interpreter procrastination”
  2. EuroPython 2026 · keynote

    Core.py live with Guido van Rossum

    Łukasz Langa and I recorded an episode of the core.py podcast live on the EuroPython main stage. Guido van Rossum was our guest. With Łukasz Langa and Guido van Rossum.

    Play “Core.py live with Guido van Rossum”
  3. Python Language Summit 2026 (EuroPython) · summit

    One namespace to namespacing them all

    I proposed to move the standard library into its own top-level namespace, apart from PyPI packages. I asked if the multi-year migration is worth it.

  4. PyCon US 2026 · panel

    Python Steering Council Panel

    The 2026 Python Steering Council answers questions about the state of Python, CPython governance and the core team. With Barry Warsaw, Donghee Na, Savannah Ostrowski and Thomas Wouters.

    Play “Python Steering Council Panel”
  5. PyCon US 2026

    Tachyon: Python 3.15's sampling profiler is faster than your code

    Tachyon is the sampling profiler in Python 3.15. It reads the memory of a running process without stopping it and decodes the interpreter state from outside. With László Kiss Kollár.

    Play “Tachyon: Python 3.15's sampling profiler is faster than your code”
  6. PyCon US 2026 · keynote · ES

    Horizonte de sucesos / Event Horizon

    The first keynote in Spanish at PyCon US, with live English captions and audio. It is about how a large group of people builds Python, and what AI-generated contributions mean for the core team.

    Play “Horizonte de sucesos / Event Horizon”
  7. PyAI London at AI Engineer Europe 2026

    Maintaining OSS in the age of AI

    AI-generated pull requests are fast to submit and slow to review. We talk about what this does to open source maintainers. With David Hewitt.

    Play “Maintaining OSS in the age of AI”

2025

  1. PyConES 2025 · ES

    Cómo todo va a cambiar para los debuggers en Python 3.14

    PEP 768 lets debuggers attach safely to a running Python 3.14 process, at no performance cost. I explain why we needed it and how it works, with pdb attached live.

    Play “Cómo todo va a cambiar para los debuggers en Python 3.14”
  2. Play “Parsers, Threads and Labyrinths”
  3. PyCon Portugal 2025 · keynote

    Um Siri fazendo barra

    The talk compares a crab doing pull-ups, Python and PEG parsers. Each one tries ordered alternatives, backtracks when needed and commits to what works.

    Play “Um Siri fazendo barra”
§ VI guest appearances

Podcasts

I also talk about CPython on other people's shows. These are the recordings that I know about, newest first.

21 recordings on 14 shows since 2020. Two are in Spanish. I was on Talk Python To Me four times, Python Discord three times, The Real Python Podcast three times and The Stack Overflow Podcast two times.

Podcast episodes 15

  1. Behind the Commit

    Behind the Python Release: Motivation, Fails & Rituals

    Recorded live at EuroPython 2025 in Prague. Three CPython release managers talk about how a release works, our best and worst releases, and our release rituals. We also talk about how to pay for open source.

    With Łukasz Langa and Hugo van Kemenade. Host: Mia Bajić. Video.

  2. The Changelog #611

    Free-threaded Python

    Before Python 3.13 came out, Łukasz and I talked about the free-threaded build, the new JIT, the yearly release cycle and iOS support.

    With Łukasz Langa. Host: Jerod Santo.

  3. The Python Show #16

    Python Core Development with Pablo Salgado

    Just before Python 3.12, I talk about core development, the Steering Council, release management and Memray.

    Host: Mike Driscoll.

  4. Talk Python To Me #425

    Memray: The endgame Python memory profiler

    Matt Wozniski and I explain Memray, the tracing memory profiler for Python and native extensions that we wrote at Bloomberg.

    With Matt Wozniski. Host: Michael Kennedy. Video.

  5. The Stack Overflow Podcast #593

    How the Python team is adapting the language for an AI future

    Part two. We talk about how Python changes for AI and data science, how we design the language, the GIL and the Faster CPython work.

    Host: Ben Popper and Kyle Mitofsky.

  6. The Stack Overflow Podcast #592

    What it's like to be on the Python Steering Council

    Part one. I went from a PhD on rotating black holes to CPython, and from typo fixes to core developer. Then we talk about the Steering Council.

    Host: Ben Popper and Kyle Mitofsky.

  7. Talk Python To Me #419

    Debugging Python in Production with PyStack

    Matt Wozniski and I show how PyStack inspects hung processes and core dumps, with mixed Python and C++ stacks and local variables.

    With Matt Wozniski. Host: Michael Kennedy. Video.

  8. Python Bytes #316

    Python 3.11 is here and it's fast (crossover)

    A rerun: the same recording as Talk Python To Me #388.

Show all 15 Show fewer
  1. Talk Python To Me #388

    Python 3.11 is here and it's fast

    I was the 3.11 release manager. Four core developers talk about the release process, the Faster CPython work, the better error messages and exception groups.

    With Irit Katriel, Mark Shannon and Brandt Bucher. Host: Michael Kennedy. Video.

  2. The Real Python Podcast #130

    Fostering an Internal Python Community & Managing the 3.11 Release

    I talk about the Python Guild, the internal Python community at Bloomberg. Then I talk about how I manage the Python 3.11 release.

    Host: Christopher Bailey.

  3. The Real Python Podcast #128

    Using a Memory Profiler in Python & What It Can Teach You

    I come back to talk about Memray, a tracing memory profiler, and what a profile can tell you about a codebase.

    Host: Christopher Bailey.

  4. The Real Python Podcast #105

    Creating Better Error Messages for Python 3.10 & 3.11

    How the PEG parser helps to find the location of a syntax error. Also, the work behind the better error messages in Python 3.10 and 3.11.

    Host: Christopher Bailey.

  5. Talk Python To Me #350

    Python Steering Council 2021 Retrospective

    The 2021 Steering Council looks back at the decisions of the year, at governance and at release management.

    With Barry Warsaw, Carol Willing, Brett Cannon and Thomas Wouters. Host: Michael Kennedy.

  6. República Web República Python II in Spanish

    Trabajar en el core de Python con Pablo Galindo

    In Spanish. How I went from physics to CPython, how Python gets its money and what a core developer does each day. We also talk about the PEP process and new features.

    Host: Andros Fenollosa. Apple Podcasts.

  7. Podcast.__init__ #285

    The Journey To Replace Python's Parser And What It Means For The Future

    Lysandros, Guido van Rossum and I replaced the LL(1) parser of CPython with a PEG parser in Python 3.9. We explain how, and what it makes possible, such as pattern matching.

    With Lysandros Nikolaou. Host: Tobias Macey.

Esferas Invisibles cover art: the show name in white capitals over particle tracks

My other show in Spanish

Esferas Invisibles

Esferas Invisibles is a science podcast in Spanish. Braulio Valdivielso and I host it. Topics include black holes, the abc conjecture, leap seconds, mantis shrimp and AI girlfriends.

“Esferas Invisibles es como deambular por wikipedia, pero en audio.” (Esferas Invisibles is like a walk through Wikipedia, but in audio.)

19 episodes 2 seasons 2022–2023 14 hours

All 19 episodes Hide episodes
  1. Season 2, episode 13: Novias artificiales · 40m
  2. Season 2, episode 12: ¿Es posible destruir un agujero negro? · 58m
  3. Season 2, episode 10: ¿Será este episodio del podcast el más escuchado en 2023? (30%) · 55m
  4. Season 2, episode 9: Las mareas no son cosa menor. Dicho de otra manera: son cosa mayor · 1h 07m
  5. Season 2, episode 8: Alienígenas agarrones · 49m
  6. Season 2, episode 7: La dramática historia de la escalera relativista y el cobertizo · 55m
  7. Season 2, episode 6: ¿Es que nadie va a pensar en los 2 billones de niños? · 40m
  8. Season 2, episode 5: Espaguetis estelares y lasañas cósmicas · 53m
  9. Season 2, episode 4: Lo que no hace la maquina es fabricar otras maquinas · 39m
  10. Season 2, episode 3: ¡Camarero! ¡Este café que me ha puesto tiene temperatura negativa! · 51m
  11. Season 2, episode 2: 404 - Not Found · 32m
  12. Season 2, episode 1: Todo esta mal con el comienzo del universo · 42m
  13. Season 1, episode 7: 23:59:60 · 42m
  14. Season 1, episode 6: Las palabras que las mujeres conocen pero los hombres no · 10m
  15. Season 1, episode 5: El crustáceo asesino que ve más colores que tu · 41m
  16. Season 1, episode 4: El pan vertical es más caro que el pan horizontal...¡la razón te sorprenderá! · 38m
  17. Season 1, episode 3: El gobierno nos oculta que el sol es verde · 45m
  18. Season 1, episode 2: Esta teoría inter-universal demuestra la conjetura abc - los matemáticos la odian · 29m
  19. Season 1, episode 1: Gravedad repulsiva · 32m