Nov 04: Command Line Scripts and Lists of Lists
Learning Objectives
After today's class, you should be able to:
- Name and describe three commands used in the terminal.
- Explain sys.argv and what command-line arguments are.
- Summarize what you can do with the os and sys modules.
- Write code that reads or writes a file using a with statement.
- Explain the syntax and meaning of a list/set/dict comprehension.
Announcements¶
-
Project 2 (due Nov 12)
- Part A Due Thursday, Nov 6
- Part B Due Wednesday, Nov 12
-
Practice Quiz 5 will be Thursday Nov 6
Hints on PA2, Part A¶
[10 min]
- See Clarifications posted this past Monday
- Turn on type hint checking
- Press F1 to open the command paletter
- Type
work jsonand pressenter- This will open a file named
settings.json
- This will open a file named
- Add/update the following setting between the curly braces:
"editor.rulers": [100], "python.analysis.typeCheckingMode": "basic", - And after
"."under"python.testing.pytestArgs"add:"-v", - This will make the pytest output more verbose
- Do not "hard code" file paths
- For example, don't do this:
# WRONG, the CS149/PA2 folder won't exist on Gradescope!
with open("CS149/PA2/log.txt") as file:
...
- Instead, use this pattern to get the "current" path:
path = os.path.join(os.path.dirname(__file__), "log.txt")
with open(path) as file:
Example
If your script my_script.py is located in /home/user/project/, and you run it from a different directory like /tmp/, this expression ensures the path resolves to /home/user/project/log.txt, rather than trying to find a file in /tmp/log.txt.
The Command Line¶
[5 min]
- Also known as the "command line" or "terminal"
- Take time after class to learn a few commands
- Tutorial by Django Girls (for beginners)
- Tutorial by Real Python (more advanced)
- Important symbols
~(tilde) means home directory.(dot) means current director..(dot dot) means parent directory
Program Arguments¶
[5 min]
- Optional arguments can be given to a program on the command line.
- sys.argv is the list of command-line arguments passed to program.
Example1: Printing Arguments
| print_args.py | |
|---|---|
1 2 3 4 5 6 7 8 | |
Walking the File System¶
[10 min]
- Demo of the
osmodule and thesysmodule - Step through this program using the debugger
Example 2: Finding Python Files
| search.py | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
In-Class Practice¶
[20 min]
Exercise
Implement the wc command on Unix systems:
- Write a command line script named word_count.py.
- If no arguments are given, print the following message:
print("Usage: python word_count.py FILE [FILE ...]")
print("Count lines, words, and chars in each file.")
- For each command line argument:
- Check if os.path.exists() before opening the file.
- Count how many lines, words, and chars are in the file.
- Print the results in this format:
py print(f"{line_count:5d} {word_count:5d} {char_count:5d} {path}")
File I/O Debrief¶
[5 min]
Refer to Thursday's activity
-
Question 3: Write a file
with open("lines.txt", "w") as file: for i in range(1, 101): file.write(f"Line #{i}\n") -
Question 4: Read a file
with open("names.txt") as file: for line in file: words = line.split() print(words[1])
Comprehension¶
[10 min]
A concise way to build a new list, set, or dictionary
List comprehension:
new_list = [expression for item in iterable if condition]
Set comprehension:
new_set = {expression for item in iterable if condition}
Dict comprehension:
new_dict = {key_exp: value_exp for item in iterable if condition}
Example 1¶
-
Building a simple list:
squares = [] for x in range(10): squares.append(x ** 2) -
Can be rewritten as:
squares = [x ** 2 for x in range(10)]
Example 2¶
-
Adding an if statement:
squares = [] for x in range(10): if x % 2 == 0: squares.append(x ** 2) -
Can be rewritten as:
[x ** 2 for x in range(10) if x % 2 == 0]
Example 3¶
-
Practice Quiz 4:
- the way you may have written the code
def limit_letters(counts, limit): result = set() for letter, count in counts.items(): #counts is a dictionary if count <= limit: result.add(letter) return result- comprehension way to express the same
def limit_letters(counts: dict, limit: int) → set: """Get letters that don't exceed a count limit.""" return {letter for letter in counts if counts[letter] <= limit}Lists of Lists¶
[10 min]
Data types from PA 2:
- A "cell" is a list of strings:
Cell = list[str]- A "grid" is a list of cells:
Grid = list[Cell]In other words, a grid is a list of list of strings.
- Standard type hint: list[list[str]]
- See
test_read_file()in test_file_utils.py
2D lists have two indexes:
grid[n][0]means "letter of nth cell"grid[n][1]means "color of nth cell"