diff options
author | Pjotr Prins | 2023-12-03 09:42:57 -0600 |
---|---|---|
committer | Pjotr Prins | 2023-12-03 09:42:57 -0600 |
commit | f63f9df201c3ae57ad8b52cf5127995c82944be7 (patch) | |
tree | 00731e4b2e5b0fd4434a8b9b308703ded915df22 /topics/using-pdb-to-troubleshoot.gmi | |
parent | fe2d644507548dcbaaf8d675d2e5c96795101d70 (diff) | |
download | gn-gemtext-f63f9df201c3ae57ad8b52cf5127995c82944be7.tar.gz |
Moving files
Diffstat (limited to 'topics/using-pdb-to-troubleshoot.gmi')
-rw-r--r-- | topics/using-pdb-to-troubleshoot.gmi | 131 |
1 files changed, 0 insertions, 131 deletions
diff --git a/topics/using-pdb-to-troubleshoot.gmi b/topics/using-pdb-to-troubleshoot.gmi deleted file mode 100644 index 294486f..0000000 --- a/topics/using-pdb-to-troubleshoot.gmi +++ /dev/null @@ -1,131 +0,0 @@ -# Using PDB to Troubleshoot Python Code - -## Tags -* type: documentation -* keywords: debugging, python - -Historically, debugging GeneNetwork code has been a bit of a pain where you would have `print' and `logging' statements to help view offending code chunks. This is not efficient, and we can do better! One painful side-effect wrt logging worth mentioning is that our logs grow quite fast and we need to rotate them, atm manually: - -Here are examples of some logging that we do: - -``` -@app.route("/n/logout") -def logout(): - logger.debug("Logging out...") - UserSession().delete_session() - flash("You are now logged out. We hope you come back soon!") - response = make_response(redirect(url_for('index_page'))) - # Delete the cookie - response.set_cookie(UserSession.user_cookie_name, '', expires=0) - return response -``` - -``` -@app.route("/tmp/<img_path>") def -tmp_page(img_path): logger.info("In tmp_page") -logger.info("img_path:", img_path) -logger.info(request.url) initial_start_vars = -request.form logger.info("initial_start_vars:", -initial_start_vars) imgfile = -open(GENERATED_IMAGE_DIR + img_path, 'rb') imgdata -= imgfile.read() imgB64 = -base64.b64encode(imgdata) bytesarray = -array.array('B', imgB64) return -render_template("show_image.html", -img_base64=bytesarray) -``` - -Earlier this year, one of our members introduced us to pudb---a graphical based logging utility for Python. I have gravitated away from this because it adds yet another dependency in our toolchain; in addition to it being ncurses-based, lacking guarantees in how it behaves in different terminals. It also lacks support in different OS'es, thereby forcing end-users to SSH into one of our remote servers to troubleshoot. - -Python PDB ships with Python, and as such, works well in different setups. There are multiple ways of getting into a pdb session, the easiest being to set a `breakpoint()'. Assume we are trouble-shooting this function: - -``` -from typing import List - - -def avg(numbers: List) -> int: - return sum(numbers)/len(numbers) - - -print(avg([20, 21])) -``` - -This will fail for a list that contains non-integer value, say a list containing ["1", "2"]. The first step to troubleshoot, assuming we have no test would be to set a `breakpoint()' as such: - -``` -from typing import List - - -def avg(numbers: List) -> int: - breakpoint() - return sum(numbers)/len(numbers) - - -print(avg([20, "21"])) -``` - -Useful commands while you are in pdb that are useful: - -* "l ." --- show where you are in the context -* "n" --- go to the next line -* "s" --- step into a function -* "c" --- continues execution until a breakpoint is encountered -* "p" --- print a variable -* "pp" --- pretty print a variable - -When we step into our debug session, we can view all the variables in a local scope using: "locals()"; and the global scope using: "globals()". With this information, we can quickly work out where our problem is by just inspecting the variables we have at hand. - -Another cool trick/pattern when debugging is to tell pdb to jump to where the error occured in a try/except block using `import pdb; pdb.post_mortem()' like so: - -``` -from typing import List - - -def avg(numbers: List) -> int: - try: - return sum(numbers)/len(numbers) - except Exception: - import pdb; pdb.post_mortem() - - -print(avg([20, "21"])) -``` - -With regards to testing, pdb is also integrated with test-runners. To use pdb with pytest, simply run: - -,---- -| pytest --pdb -`---- - -## Running Flask Applications Under pdb - -To troubleshoot a Flask application (and any other application running via an -applicationsserver of sorts), you might need to start the application server under -the debugger, otherwise, you will get an error like: - -``` -BdbQuit -``` - -Ideally, you shouldn't need to, as the terminal where you started the -application server (Flask) should drop you into the debugger automatically. - -If you run the application under other application servers like gunicorn, then -you might need to increase the timeout period to prevent gunicorn from killing -the process, leading to the error above. Generally speaking, you **SHOULD NOT** -be running the debugger in production anyway, and therefore you should not need -to deal with the gunicorn issues. - -That said, you can start the Flask application under pdb with something like: - -``` -python3 -m pdb flask run [OPTIONAL-ARGUMENTS-TO-FLASK] -``` - - -## Useful Tutorials - -To learn more about pdb, you can check out: - -=> https://www.youtube.com/watch?v=0LPuG825eAk python debugger crash course: pdb/breakpoint -=> https://www.youtube.com/watch?v=s8Nx2frW4ps postmortem debugging in python |