Q2

In this question, we'll review the basics of file I/O (file input/output) and the various function calls and modes required.

Part A

Write a function which:

  • is named read_file_contents
  • takes a string pathname as an argument
  • returns a single string that contains all the contents of the file

Don't import any additional packages.

If I have a file random_text.txt, I'll give the full path to this file to the function: contents = read_file_contents("random_text.txt"), and I should get back a single string contents that contains all the contents of the file.

NOTE: Your function should be able to handle errors gracefully! If an error occurs when trying to read from the file, your function should return None (note the capitalization of the first letter).


In [ ]:


In [ ]:
truth = "This is some text.\nMore text, but on a different line!\nInsert your favorite meme here.\n"
pred = read_file_contents("q1data/file1.txt")
assert truth == pred

In [ ]:
retval = -1
try:
    retval = read_file_contents("nonexistent/path.txt")
except:
    assert False
else:
    assert retval is None

Part B

In this question, you'll read from one file, perform a simple computation, and write the results to a new file.

Write a function which:

  • is named count_lines
  • that takes two arguments: the first is a path to an input file to read, the second is the path to an output file to write
  • returns True on success, False if something went wrong (i.e an error occurred)

Your function will count the number of lines in the file at the first argument, and write this number to a file at the second argument.

NOTE: Your function should be able to handle errors gracefully! If an error occurs when trying to read from the file or write to the output file, your function should return False.


In [ ]:


In [ ]:
import os
if os.path.exists("q1data/file1_out.txt"):
    os.remove("q1data/file1_out.txt")

assert count_lines("q1data/file1.txt", "q1data/file1_out.txt")
assert os.path.exists("q1data/file1_out.txt")
assert int(open("q1data/file1_out.txt", "r").read()) == 3

In [ ]:
if os.path.exists("meaningless"):
    os.remove("meaningless")

r1 = None
try:
    r1 = count_lines("yet/another/nonexistent/path.txt", "meaningless")
except:
    assert False
else:
    assert not r1

In [ ]:
r2 = None
try:
    r2 = count_lines("q1data/file1.txt", "/this/should/throw/an/error.txt")
except:
    assert False
else:
    assert not r2

Part C

In this question, you'll write a function which

  • is named acount_lines
  • takes the same two arguments as count_lines in Part B
  • returns the same values as count_lines in Part B

This function performs the same operation as before, except in the case that the output file already exists: in this case, you'll append the line count to the file instead of overwriting it, thus preserving any existing previous line counts.

Each new appended line count should be on its own line in the output file. You may need to manually insert newline characters, which are a backslash followed by the letter n: \n

Your function should return True on success, and False if an error occurred.

NOTE: Your function should be able to handle errors gracefully! If an error occurs when trying to read from the file or write to the output file, your function should return False.


In [ ]:


In [ ]:
if os.path.exists("q1data/out_again.txt"):
    os.remove("q1data/out_again.txt")

assert acount_lines("q1data/file1.txt", "q1data/out_again.txt")
assert os.path.exists("q1data/out_again.txt")
assert int(open("q1data/out_again.txt", "r").read()) == 3

In [ ]:
assert acount_lines("q1data/file2.txt", "q1data/out_again.txt")
assert os.path.exists("q1data/out_again.txt")
assert int("".join(open("q1data/out_again.txt", "r").read().split("\n"))) == 34

In [ ]:
r1 = None
try:
    r1 = acount_lines("yet/another/nonexistent/path.txt", "meaningless")
except:
    assert False
else:
    assert not r1

r2 = None
try:
    r2 = acount_lines("q1data/file2.txt", "/this/should/throw/an/error.txt")
except:
    assert False
else:
    assert not r2