Chapter 17 Applied Python Exercise 6

17.1 Goal – recreate the Bash tool head in Python; adding some new functionality that skips header lines

Write Python code that recreates the Bash tool head, displaying a default number of lines in an input file if a specific number of lines isn’t specified; but extend the tool so that it skips header lines (specifically, for this example, lines that start with a pound sign (#)).

17.2 Learning Objectives

After going through this chapter, students should be able to:

  • State the sub-steps needed to meet the coding goal
  • Use the following datatypes, structures, and fundamentals to meet the coding goal:
    • importing modules
    • variable assignment
    • list indexing
    • list length
    • integer conversion
    • opening a file
    • initializing a counter variable before a for loop
    • updating a counter variable within a the body of a for loop
    • for loop
    • chaining logical expressions
    • looking at the character a line starts with
    • conditional statement
    • printing output

17.3 Coding Blueprint

Let’s again start with and edit the pseudocode from the previous chapter to meet the needs of this chapter.

Previous chapter’s pseudocode:

First, we need to SET the input file
Next, IF the user-specified a desired number of lines to display
   THEN we need to SET the desired number of displayed lines
END IF
OTHERWISE
   THEN we need to SET the desired number of displayed lines to a default
END OTHERWISE
Then, FOR every line in the open file
   IF a desired line (by its numerical position)
     PRINT the line
   END IF
END FOR

We do want to edit this past pseudocode, adding a condition that should be true before we print a line. Edit that line of the pseudocode, expanding it with logical expression language to reflect this change in the program behavior.


ANSWER:

First, we need to SET the input file
Next, IF the user-specified a desired number of lines to display
   THEN we need to SET the desired number of displayed lines
END IF
OTHERWISE
   THEN we need to SET the desired number of displayed lines to a default
END OTHERWISE
Then, FOR every line in the open file
   IF a desired line (by its numerical position) AND NOT a header line (line doesn’t start with a pound sign #)
     PRINT the line
   END IF
END FOR


We also can no longer assume that the numerical position of the line within the file corresponds to the number of lines that have been printed since we’re filtering out the header. Therefore, we need to track the number of lines that have been printed. Add two lines to the pseudocode that will help you do this, and further edit the conditional that we check before printing a line. As a hint for those, this is the first time we’ll be using the third optional component of a for loop: initializing a variable before the for loop (and then subsequently) updating it within the body of the loop.


ANSWER:

First, we need to SET the input file
Next, IF the user-specified a desired number of lines to display
   THEN we need to SET the desired number of displayed lines
END IF
OTHERWISE
   THEN we need to SET the desired number of displayed lines to a default
END OTHERWISE
SET counter of number of lines that have been displayed to 0
Then, FOR every line in the open file
   IF a desired line (counter hasn’t reached desired number of lines) AND NOT a header line
     PRINT the line
     SET counter to ADD one
   END IF
END FOR


17.4 Building the code

Create a new Python script

17.4.1 Usage statement and module importing

The usage statement and module importing from the previous Applied Python Exercise chapter are still accurate for this chapter, so go ahead and reuse the usage and import statements from the fifth Applied Python Exercise chapter within your new Python script.


ANSWER:
#USAGE: python scriptname.py input_filename [number_lines_to_display]
import sys

17.4.2 SET the input filename

Within your Python script, set the filename variable to be equal to the first command line argument like you did in fourth and fifth Applied Python Exercise chapters.


ANSWER:
filename = sys.argv[1]

17.4.3 IF the user-specified a desired number of lines to display

Within your Python script, set up the conditional statement structure like you did in the fifth Applied Python Exercise chapter to check if the user has provided a desired number of lines to display.


ANSWER:
if len(sys.argv) > 2:

17.4.4 THEN SET the desired number of lines

Within your Python script, use the variable assignment statement from the fourth and fifth Applied Python exercise chapters to define the desired number of lines as specified by the user, indenting under the conditional statement.


ANSWER:
  n_lines = int(sys.argv[2])

17.4.5 OTHERWISE

Use the alternate conditional statement structure from the fifth Applied Python Exercise chapter to start defining the alternate behavior we will want (in how we define the desired number of lines variable in cases where the user didn’t specify a specific value). Put this statement in your Python script.


ANSWER:
else:

17.4.6 THEN SET the desired number of lines to a default

Use the alternate variable assignment statement from the fifth Applied Python Exercise chapter to define the desired number of lines variable if the user didn’t specify a specific value. Put this statement in your Python script, indented correctly.


ANSWER:
  n_lines = 10

17.4.7 SET counter of number of lines that have been displayed to 0

Because we no longer assume that the numerical position of the line within the file corresponds to the number of lines that are printed, since we’re filtering out the header lines, we need to define a counter variable we can use to track the number of lines that we print. When first initializing this variable, we haven’t printed any lines. Therefore, you want to set the counter variable equal to the value of zero. Do this within your Python script.


ANSWER:
counter = 0

17.4.8 FOR every line in the open file

Next, we no longer need to track the position of the line in the file. We only want to work with each line line-by-line in the open file. Therefore, we can go back to the for loop statement that we used in the first Applied Python Exercise chapter. Add the appropriate for loop statement to your Python script.


ANSWER:
for line in open(filename):

17.4.9 IF a desired line (because counter hasn’t reached the desired number of lines) and NOT a header line

Let’s break this task down into two separate conditions and then chain the conditions together into one conditional expression.

First, we want to check if the value of the counter is less than the number of desired lines. Write an expression that will evaluate to a boolean variable answering whether an integer is less than another integer. Use the appropriate variable names that refer to the integer variable we’re interested in.


ANSWER:
counter < n_lines

Next, we want to verify that the specific line we’re working with is not a header line. Specifically, does the line not start with a pound sign ("#")? Consult the Python notes on negating a boolean expression and checking if a string variable starts with a specific character. Then write an expression that will evaluate to a boolean variable answering whether the line does not start with the pound sign ("#"). Make sure to use the appropriate variable name in the expression.


ANSWER:
not line.startswith("#")

Now, chain the expressions together within your Python script to form a chained conditional expression, within the body of the for loop, indented correctly under your for loop statement. Recall that you want both booleans to be True for the conditional’s body (printing the line) to be executed.


ANSWER:
  if counter < n_lines and not line.startswith("#"):

17.4.11 SET counter to ADD one

If we were to end writing the program now, our script would print every line in the file that wasn’t a header line. What can we do to avoid this and only print the specific number of lines we want?


ANSWER: To avoid this, we have to update the counter every time we print a line so we have an accurate count of the number of lines we’ve printed.

Write a variable assignment statement within your Python script that updates the value of the counter variable, adding one to it. Make sure it is appropriately indented in line with the print statement under the conditional statement.


ANSWER:
    counter = counter + 1

Within your Python script, you should now have the twelve lines of code together which makes our complete intended goal code – code that prints a user specified number of lines from the beginning of a user specified input file, skipping header lines that begin with a pound sign (#).

Use the command line or the Run button in the online interface to run the Python script and look at the output.

17.5 Complete Intended Goal Code


ANSWER:
#USAGE: #USAGE: python scriptname.py input_filename [number_lines_to_display]
import sys #import module
filename = sys.argv[1] #SET the input filename
if len(sys.argv) > 2: #IF user-specified number of lines provided
  n_lines = int(sys.argv[2]) #SET the desired number of lines
else: #OTHERWISE
  n_lines = 10 #SET the desired number of lines to a default
counter = 0 #SET counter of number of lines that have been displayed ot 0
for line in open(filename): #FOR every line in the open file
  if counter < n_lines and not line.startswith("#"): #IF the counter hasn't reached the max number of desired lines AND NOT a header line
    print(line.strip('\r\n')) #PRINT the line
    counter = counter + 1 #SET counter to add one