Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lesson demo #93

Merged
merged 2 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions clean-modular-code/activity-3/clean-code-activity-3.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ As you make decisions about adding checks to your code, weigh the value of using
# This fails with a FileNotFound Error
from pathlib import Path

file_path = Path("aadata-bad-path") / "2022-03-joss-publications.json"
file_path = Path("data-bad-path") / "2022-03-joss-publications.json"

try:
print(file_path)
Expand All @@ -71,6 +71,8 @@ try:
json_clean = pd.json_normalize(json_data)
except:
print("This doesn't fail fast, it only prints a message")

print("Look, i keep running after the try/except block which means I didn't fail")
```

+++ {"editable": true, "slideshow": {"slide_type": ""}}
Expand All @@ -83,7 +85,7 @@ If you are processing specific data in your workflow, then ensuring your code ca

If your code doesn't [fail fast](fail-fast) with a useful error message, and it continues to run and fails later, it will potentially confuse a user. The error that will likely be raised later will likely not alert the user that the issue is actually missing data vs something else.

This will then mislead someone when trying to troubleshoot your code.
This will then mislead someone when trying to troubleshoot your code.

+++

Expand Down Expand Up @@ -123,7 +125,7 @@ Turn the code below into a function.
Modify the function below so it raises catches the errror and prints a custom error but does not
stop your code from continuing to run.

Consider the difference between the funciton the funciton that you created above that stops your code from running by raising an exception compared to this code that prints a statement for the user.
Consider the difference between the funciton the funciton that you created above that stops your code from running by raising an exception compared to this code that prints a statement for the user.

```{code-cell} ipython3
---
Expand Down
66 changes: 39 additions & 27 deletions clean-modular-code/clean-code-present.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ kernelspec:

+++ {"editable": true, "slideshow": {"slide_type": "slide"}}

# Clean, Modular Code
# Clean, Modular Code: overview

+++ {"editable": true, "slideshow": {"slide_type": ""}}

Expand All @@ -23,10 +23,8 @@ kernelspec:
* Use [expressive object names](python-expressive-code)
* [Make your code DRY](dry-code)


+++ {"editable": true, "slideshow": {"slide_type": "slide"}, "jp-MarkdownHeadingCollapsed": true}


### PEP 8 & consistent code format

* Generally accepted rules for code format: PEP 8
Expand All @@ -35,13 +33,13 @@ kernelspec:

+++ {"editable": true, "slideshow": {"slide_type": "skip"}}


## Notes


```{code-cell} ipython3
---
editable: true
jupyter:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i am not sure what this is? or where it came from.

source_hidden: true
slideshow:
slide_type: ''
---
Expand Down Expand Up @@ -77,10 +75,8 @@ if x:
* Black
* Ruff


+++ {"editable": true, "slideshow": {"slide_type": "slide"}, "jp-MarkdownHeadingCollapsed": true}


#### [Other tools to consider](tools-code-style)

* `pre-commit` hooks: use with .git; apply every time you commit changes
Expand All @@ -95,7 +91,11 @@ if x:

+++ {"editable": true, "slideshow": {"slide_type": "slide"}}

<center><img src="../images/clean-code/clean-code-expressive-variable-names-basmati-rice.png" alt="Image showing a large see-through Tupperware container with cookies in it but a label that says Basmati Rice."></center>
:::{figure} /images/clean-code/clean-code-expressive-variable-names-basmati-rice.png
:alt: "Image showing a large see-through Tupperware container with cookies in it but a label that says Basmati Rice."

A large see-through Tupperware container labeled "Basmati Rice" containing cookies.
:::

```{code-cell} ipython3
---
Expand Down Expand Up @@ -194,14 +194,14 @@ Three strategies:

+++ {"editable": true, "slideshow": {"slide_type": "slide"}}

## Document as you go
### Document as you go

* Make it a habit
* It's easier to do it as you work!

+++ {"editable": true, "slideshow": {"slide_type": "slide"}}

## Document your code
#### Document your code

Add a docstring to the top of any script or module that explains the intent of the code.

Expand Down Expand Up @@ -313,7 +313,7 @@ help(add_num)

+++ {"editable": true, "slideshow": {"slide_type": "slide"}}

## Modularize your code
### Modularize your code

Functions make code easier to read, test, and maintain.

Expand Down Expand Up @@ -351,7 +351,7 @@ for num in numbers:

+++ {"editable": true, "slideshow": {"slide_type": "slide"}}

## Reproducibility: Create dynamic paths
## Make your code reproducibe across machines with dynamic paths

* Paths on Windows are different than MAC/Linux
* Using `Path` (or `os`)
Expand Down Expand Up @@ -384,20 +384,19 @@ print(path)

## Tests & checks

* Usability sometimes means failing (gracefully and with intention).

* Usability sometimes means failing (gracefully and with intention).

+++ {"editable": true, "slideshow": {"slide_type": "slide"}}

### Strategies
* Fail fast (with useful error messages)
* try/except blocks: handle errors (exceptions)
* Conditionals to optimize and redirect workflows
### 3 Strategies

+++ {"editable": true, "slideshow": {"slide_type": "slide"}}
* **Fail fast** (with useful error messages)
* **try/except blocks:** handle errors (exceptions)
* **Conditionals** to optimize and redirect workflows

## Fail fast
+++ {"editable": true, "slideshow": {"slide_type": "slide"}}

### Fail fast

```{code-cell} ipython3
---
Expand All @@ -423,6 +422,13 @@ with file_path.open("r") as json_file:
df = pd.json_normalize(json_data)
```

When your code doesn't fail fast, it might fail somewhere different.
In this case, `.glob` can't find any files so the list of paths is empty.

In this case, the file can't be opened but it failes because file_path is an
empty list when the real problem is it's missing fail paths. This type of
error is confusing to a user and will take longer to debug.

```{code-cell} ipython3
---
editable: true
Expand All @@ -439,7 +445,7 @@ import pandas as pd
# Create a list of json files
file_paths = list(Path(".").glob("*.json"))
# Open the first file
with file_path[0].open("r") as json_file:
with file_paths[0].open("r") as json_file:
json_data = json.load(json_file)

# Normalize the JSON data into a Pandas DataFrame
Expand All @@ -458,7 +464,7 @@ file_paths

+++ {"editable": true, "slideshow": {"slide_type": "slide"}}

## Handle errors
### Handle errors with try/excepts

* Anticipate errors a user may encounter when using your code.
* Redirect workflows by catching errors.
Expand Down Expand Up @@ -500,14 +506,19 @@ package_name = title.split(":")[0]
package_name
```

In some cases, you may want to capture the error and return a default value
(or do something else).

:::{figure} /images/clean-code/try-except-blocks.png
:alt: "An illustration showing a basic Python try and except block. Under “try:”, there is a green box with the text “Code runs as planned! Yay!”. Below that, under “except:”, there is a light yellow box with the text “Code fails, Do something else”. The image has a minimalist style with a small flower icon and a wavy line header at the top, and includes the pyOpenSci logo in the bottom right corner."
:::

```{code-cell} ipython3
---
editable: true
slideshow:
slide_type: slide
---
# In some cases, you may want to capture the error and return a default value
# (or do something else)
title = 9999

try:
Expand All @@ -521,14 +532,15 @@ except AttributeError:
package_name
```

In other cases you may want to intentionally raise an error with a custom message.

```{code-cell} ipython3
---
editable: true
slideshow:
slide_type: slide
tags: [raises-exception]
---
# In others you may want to intentionally raise an error with a custom message.
title = 999

try:
Expand All @@ -543,8 +555,8 @@ package_name

+++ {"editable": true, "slideshow": {"slide_type": "slide"}}

## Start activity three
## You're ready for activity three

Activity 3 is an interactive notebook you can work on in small groups.
[Activity 3 is an interactive notebook](clean-code-activity-3) you can work on in small groups.

Work through the activities and ask questions!
Binary file added images/clean-code/try-except-blocks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.