Concepts / File Input and the open() Function

File Input and the open() Function

A file line includes the newline character at its end when it is read in a for loop.

  • Programming
Interactive lab

Try it: Reading and Writing Text Files

How open() returns a file object with a position pointer, how read(), read(n), readline(), readlines() and for line in fh advance it (and return '' at the end), how 'w' and 'a' modes change the file, and why a closed file (after close() or a with block) can no longer be read.

How it works

  1. open(name, 'r') starts the pointer at 0; 'w' empties the file first; 'a' starts at the end.
  2. read() returns everything from the pointer to the end; read(n) at most n characters; readline() up to and including the next \n; each moves the pointer past what it returned.
  3. At the end of the file every read returns '' (an empty string), which is how loops know to stop; for line in fh reads line by line the same way.
  4. write() text waits in a buffer and reaches the file when it is closed (or the program ends); reading a 'w'/'a' file or writing an 'r' file raises io.UnsupportedOperation.
  5. close(), or leaving a with block, closes the file; any further read raises ValueError: I/O operation on closed file.

Default run (10 steps): Ready: notes.txt holds 4 lines (51 characters). Nothing is open yet. … Finished. notes.txt now holds "From: stephen\nSubject: meeting\nFrom: louis\nThanks!\n".

Simplified: The lab's own small Python interpreter runs a fixed, hand-written script (you choose the variant and the values, never the code); nothing is executed as real Python. Every script was run in CPython 3.12 with the same inputs and the lab reproduces its output and error messages. One virtual text file with \n line endings (as on Linux/macOS), positions counted in characters (ASCII only), and a write buffer that is only flushed by close() or the end of the program.

Educational simulation

Loading the simulation…

A Search Produces a Position

When find() searches a string, it returns one integer. If the substring exists, the integer identifies the character position where that substring starts. If the substring does not exist, find() returns -1. This makes the method useful for examining file lines and deciding which lines should be kept.

Key point

The first character has index 0, not index 1. A returned index is the starting position of the complete substring.

What do you think happens?

In the string From: alice@example.com, what does find() return when searching for @?

  • 0

  • 6

  • 11

  • -1

Reveal answer
Answer:

11

The first character is at index 0. Counting from zero, the @ character is at index 11.

Mapping Characters to Indexes

To debug find(), write the string out with its character positions. In the generated example below, the search substring is @. The returned value is not a count of all characters and not a true-or-false result. It is the position of the first character in the substring.

Findex 0find result11rindex 1oindex 2mindex 3:index 4spaceindex 5aindex 6lindex 7iindex 8cindex 9eindex 10@index 11substring starts here
How does find() map the substring @ to its starting character position?
Worked example

Tracing an Email Address

Determine the result of searching for @ in the string From: alice@example.com.

  1. 1
    Start at index 0

    The first character, F, is at position 0, so every later character is counted from that starting point.

  2. 2
    Count to the match

    The @ character appears after the characters From: and the space and the five letters in alice. Its zero-based position is 11.

  3. 3
    Interpret the result

    find() returns 11 because the searched substring begins at index 11.

Result

The search returns 11.

Three Return Values

find() resultMeaningTypical interpretation
0The substring starts at the first character.The line begins with the searched substring.
A positive indexThe substring starts later in the string.The line contains the substring after one or more earlier characters.
-1The substring was not found.Reject or skip the string when filtering for the substring.

The integer returned by find() tells you where the substring starts or that no match exists.

0match starts firstsubstring at startpositive indexmatch starts latersubstring later-1no matchsubstring absentmeansmeansmeans
What is the difference between a result of 0, a positive index, and -1?

Filtering Lines from a File

The useful file-search pattern combines three actions: open the file, process each line in a loop, and use find() inside a conditional statement. The line is cleaned with rstrip() before the search. If find() returns -1, continue skips that line. Otherwise, the line is printed.

Code walkthrough
fhand = open('mbox-short.txt')
for line in fhand:
    line = line.rstrip()
    if line.find('From:') == -1:
        continue
    print(line)
  1. 1
    The open() call opens the file named mbox-short.txt.
  2. 2
    The for loop obtains one line at a time from the opened file.
  3. 3
    rstrip() removes trailing whitespace before the search.
  4. 4
    find('From:') returns either the starting index of From: or -1.
  5. 5
    When the result is -1, continue moves to the next line without printing.
  6. 6
    When the result is not -1, print(line) displays the matching line.
  • Open mbox-short.txt so its lines can be processed.
  • Process each line from the opened file.
  • Remove trailing whitespace, including the line-ending newline.
  • Search for the substring From: and compare the result with -1.
  • Skip this line when the substring was not found.
  • Print the line when find() returned an index rather than -1.
file lineafter rstrip()find('From:')-1?continuereject lineprint(line)accept linesearchinteger resultyes: -1no: index found
How does control flow branch when find() returns an index or -1?
Output
From: alice@example.com
From: bob@example.com

Following the Matching Data

Each file line follows the same path: it comes from the opened file, has trailing whitespace removed, and is tested with find(). A line whose result is -1 leaves the output collection because continue skips it. A line whose result is 0 or a positive index passes the test and is printed. The method therefore acts as a filter rather than merely reporting a position.

mbox-short.txteach linerstrip()remove trailing whitespacefind('From:')matching linesreadprocesssearchindex found
How do lines move from an opened file through the substring test into the matching output?
Best practice

Treat the return value as diagnostic information. When a line is unexpectedly accepted or rejected, inspect the exact integer from find(), then compare that result with -1. This reveals whether the substring was found and where it began.

Mistakes with File Searches

  • Common mistake

    Treating 0 as if it meant no match.

    What it looks like
    A line begins with From:, so find('From:') returns 0.
    Why it fails

    Zero is a valid index. It means the substring starts at the first character.

    Do this instead

    Use -1 as the not-found result. A result of 0 or a positive index means that the substring was found.

  • Common mistake

    Checking only for a positive result.

    What it looks like

    A condition accepts the line only when find('From:') is greater than 0.

    Why it fails

    That condition rejects a valid match at index 0.

    Do this instead

    Test whether the result is -1 when you need to distinguish absence from presence.

  • Common mistake

    Searching before removing trailing whitespace.

    What it looks like

    The loop searches the line exactly as it was read from the file.

    Why it fails

    A line read from a file includes a newline character at the end, and trailing whitespace can make searches behave unexpectedly.

    Do this instead

    Call rstrip() before calling find() so the search uses the line's content without trailing whitespace.

  • Common mistake

    Assuming find() returns the number of matching characters.

    What it looks like

    The search for From: returns 5 because the substring has five characters.

    Why it fails

    find() returns the starting index, not the length of the substring.

    Do this instead

    Trace the characters from index 0 and identify where the first character of the searched substring begins.

Practice the Trace

EASY

For each string, determine the result of find('cat'). Then decide whether the line would be printed by a filter that skips only when the result equals -1: catalog, bobcat, and dog.

Hints
  • Start counting at index 0.
  • The substring can begin at index 0 or at a positive index.
  • Only a result of -1 causes the line to be skipped.
Worked example

Checking the Practice Strings

Determine the find('cat') result for catalog, bobcat, and dog.

  1. 1
    catalog

    The substring cat starts at the first character, so the result is 0. The line passes the filter.

  2. 2
    bobcat

    The substring cat starts after bob. With zero-based indexing, its starting position is 3. The line passes the filter.

  3. 3
    dog

    The substring cat is absent, so the result is -1. The line is skipped.

Result

catalog and bobcat are accepted; dog is rejected.

Key Takeaways

  1. 1
    find() returns the starting index of a found substring.
  2. 2
    Indexes are zero-based, so the first character is at position 0.
  3. 3
    A result of 0 is a valid match at the beginning, a positive result is a match later in the string, and -1 means no match.
  4. 4
    For file filtering, open the file, process each line, call rstrip(), and use find() in a conditional statement.
  5. 5
    When debugging, trace the returned index and check whether it equals -1.

At a glance

  • find() reports where a substring begins or returns -1 when it is absent.
  • The returned position uses zero-based indexing.
  • A file-search loop can use rstrip(), find(), and continue to filter lines.
  • Checking the exact integer returned by find() is a reliable way to debug substring searches.

More concepts starting with F