In an ideal world, you would write Python code and then it would work perfectly. But unfortunately, it doesn't work in this manner. In my talk, I'll cover how to efficiently debug your programs, especially in cloud environments or inside Kubernetes.
10. viaREPL?
andrii@hachyderm.io
$ python -i cycle_length.py
>>> cycle_length
<functools._lru_cache_wrapper
>>> pprint.pprint({l for l in
{'cycle_length', 'functools',
>>>
object at
locals()
'pprint',
0x104328bf0>
if not l.startswith(' ')})
'sys'}
28. andrii@hachyderm.io
Step4:Run
docker run -p 8000:8000 -p 5678:5678 asoldatenko/py-sample-app-debug
0.00s - Debugger warning: It seems that frozen modules are being used, which may
0.00s - make the debugger miss breakpoints. Please pass -Xfrozen_modules=off
0.00s - to python to disable frozen modules.
0.00s - Note: Debugging will proceed. Set PYDEVD_DISABLE_FILE_VALIDATION=1 to
disable this validation.
30. PDB CLONE Doesn’t work
with 3.12
def main():
import pdb_clone.pdb as pdb
pdb.set_trace_remote(host=b'127.0.0.1', port=7935, frame=None)
a = 2
b = 3
c = a + b
$ python samples/pdb_clone_example.py
31. PDB CLONE
$ telnet localhost
Trying ::1...
…
7935
PROCESS_PID:43030
PROCESS_NAME:samples/pdb_clone_example.py
> /users/andrii.soldatenko/work/debugging-containerized-python-applications/samples/
pdb_clone_example.py(4)main()
-> a = 2
(Pdb) n
> /users/andrii.soldatenko/work/debugging-containerized-python-applications/samples/
pdb_clone_example.py(5)main()
-> b = 3
32. PDB CLONE
-> b = 3
(Pdb) l
1 def main():
2 import pdb_clone.pdb as pdb
3 pdb.set_trace_remote(host=b'127.0.0.1',
a = 2
b = 3
c = a + b
port=7935, frame=None)
4
5 ->
6
7
8 main()
[EOF]
(Pdb)
41. docker-entrypoint.sh
https://github.com/ashleymcnamara/gophers
#!/bin/sh
...
if [ "$REMOTE_DEBUG_PORT" ]; then
echo "Starting application with remote
debugFlags="--wait-for-client --listen
main:app --port 8000 --host 0.0.0.0"
debugging on port $REMOTE_DEBUG_PORT"
0.0.0.0:$REMOTE_DEBUG_PORT -m uvicorn
# Simply setting this environment variable is enough to force the debugger to
# pause on start --- we don't care about the value.
cmd="python -m debugpy $debugFlags"
fi
…
42. docker-entrypoint.sh
#!/bin/sh
...
if [ "$REMOTE_DEBUG_PORT" ]; then
debugging on port $REMOTE_DEBUG_PORT"
0.0.0.0:$REMOTE_DEBUG_PORT -m uvicorn
echo "Starting application with remote
debugFlags="--wait-for-client --listen
main:app --port 8000 --host 0.0.0.0"
# Simply setting this environment variable is enough to force the debugger to
# pause on start --- we don't care about the value.
cmd="python -m debugpy $debugFlags"
fi
…
53. K9s: plugin.yml
plugin:
a plugin to provide a `ctrl-l` shortcut to tail the logs while
# Defines
in pod view
#--- Create debug container for selected pod in current namespace
# See https://kubernetes.io/docs/tasks/debug/debug-application/debug-
running-pod/#ephemeral-container
debug:
shortCut: Ctrl-H
description: Add debug container
scopes:
- containers
command: bash
background: false
confirm: true
args:
- -c
- "kubectl debug -it -n=$NAMESPACE $POD --target=$NAME --
image=nicolaka/netshoot:v0.11 --share-processes -- bash"
54. Summary
The debugger doesn't fix your bugs, it just runs them in slow motion.
Don’t forget to add some details to your python apps inside images
Of course, you have to scale down traffic to 1 instance to avoid misses of
requests to your pod
Use debugger as much as possible
Automate you rotine with hotkeys/plugins