{"id":"writing-files-append","slug":"append","title":"Adding to the end of a file","text":"Opening a file with `\"w\"` always starts from an empty file. To add lines to the end of a file and keep what's already in it, open it in **append** mode, `\"a\"`:\n\n```file visitors.txt\nAna\nBo\n```\n\n```python\nwith open(\"visitors.txt\", \"a\") as file:\n    file.write(\"Cy\\n\")\n    file.write(\"Dee\\n\")\n\nwith open(\"visitors.txt\") as file:\n    print(file.read())\n```\n\n```output\nAna\nBo\nCy\nDee\n```\n\nIf the file doesn't exist yet, `\"a\"` creates it, just as `\"w\"` would. So the three modes so far are:\n\n- no mode (or `\"r\"`, for read): read a file that must exist;\n- `\"w\"`, write: start a new, empty file, wiping out any old one with that name;\n- `\"a\"`, append: add to the end of a file, creating it if needed.\n\n### A log that grows\n\nAppend mode suits files that only ever grow, such as a **log**: a file where a program notes what it has done. Each call of this function opens the file, adds one line and closes it again:\n\n```python\ndef log(message):\n    with open(\"log.txt\", \"a\") as file:\n        file.write(message + \"\\n\")\n\n\nlog(\"Program started\")\nlog(\"Loaded 3 users\")\nlog(\"Program ended\")\n\nwith open(\"log.txt\") as file:\n    for line in file:\n        print(\"LOG:\", line.strip())\n```\n\n```output\nLOG: Program started\nLOG: Loaded 3 users\nLOG: Program ended\n```\n\nIf you ran this program again on your own computer, the file would get three more lines below these. (On this site, every run starts in a fresh folder with only the files the task gives.) With `\"w\"` in `log` instead, every call would empty the file before writing its line, so even a single run would leave only the last message, `Program ended`.\n\nAppending is handy, but it can only add to the end. A program that needs to change something in the middle of a file, or remove a line from it, reads the whole file, changes the data and writes all of it again with `\"w\"`. The last step of this module shows how.\n","task":"The file `shopping.txt` already has a shopping list in it. Fill in the blank so the program adds `bananas` to the end of the list and keeps the items that are already there. With this file\n\n```text\neggs\nflour\n```\n\nthe program leaves this in `shopping.txt`:\n\n```text\neggs\nflour\nbananas\n```\n","kind":"fill","seed":"with open(\"shopping.txt\", [[\"a\"‖'a']]) as file:\n    file.write(\"bananas\\n\")\n","solution":"with open(\"shopping.txt\", \"a\") as file:\n    file.write(\"bananas\\n\")\n","hints":["`\"w\"` would wipe out the list. The mode that adds to the end is a different letter.","Append mode is `\"a\"`, with its quotes."],"tests":[{"name":"Test 1","stdin":"","files":{"shopping.txt":"eggs\nflour\n"},"writes":{"shopping.txt":"eggs\nflour\nbananas\n"},"expect":"","hidden":false},{"name":"Test 2","stdin":"","files":{"shopping.txt":"rice\ncoffee\nsoap\n"},"writes":{"shopping.txt":"rice\ncoffee\nsoap\nbananas\n"},"expect":"","hidden":true}],"require":[],"forbid":[],"more":[{"task":"Write a function `add_note(note)` that adds the note as a new line to the end of the file `notes.txt`. Whatever was in the file before stays there. If the file doesn't exist yet, the function creates it.\n\nFor example, if `notes.txt` has\n\n```text\nBuy stamps\n```\n\nthen after `add_note(\"Water the plants\")` it has:\n\n```text\nBuy stamps\nWater the plants\n```\n","kind":"code","seed":"def add_note(note):\n    pass\n\n\nif __name__ == \"__main__\":\n    add_note(\"Water the plants\")\n","solution":"def add_note(note):\n    with open(\"notes.txt\", \"a\") as file:\n        file.write(note + \"\\n\")\n\n\nif __name__ == \"__main__\":\n    add_note(\"Water the plants\")\n","hints":["Open `notes.txt` in append mode, `\"a\"`, which also creates the file when it's missing.","Write the note with a line break after it: `file.write(note + \"\\n\")`."],"tests":[{"name":"add_note(\"Water the plants\")","stdin":"","call":"add_note(\"Water the plants\")\n","files":{"notes.txt":"Buy stamps\n"},"writes":{"notes.txt":"Buy stamps\nWater the plants\n"},"expect":"","hidden":false},{"name":"Test 2","stdin":"","call":"add_note(\"Call the dentist\")\nadd_note(\"Return library books\")\n","files":{"notes.txt":"Pay rent\nBuy stamps\n"},"writes":{"notes.txt":"Pay rent\nBuy stamps\nCall the dentist\nReturn library books\n"},"expect":"","hidden":true},{"name":"add_note(\"First note\")","stdin":"","call":"add_note(\"First note\")\n","writes":{"notes.txt":"First note\n"},"expect":"","hidden":true}],"require":[],"forbid":[]},{"task":"The file `scores.csv` holds the high scores of a game, one `name;score` line per game played. Write a program that asks for a player's name and score, adds them as a new line to the end of the file, and then prints every line of the file, numbered, as in the example.\n\nIf `scores.csv` has\n\n```text\nAna;950\nBo;720\n```\n\na run looks like this:\n\n```\nName: Cleo\nScore: 870\n1. Ana: 950\n2. Bo: 720\n3. Cleo: 870\n```\n\nand the file ends up with three lines, the last one `Cleo;870`.\n","kind":"code","seed":"name = input(\"Name: \")\nscore = input(\"Score: \")\n","solution":"name = input(\"Name: \")\nscore = input(\"Score: \")\n\nwith open(\"scores.csv\", \"a\") as file:\n    file.write(f\"{name};{score}\\n\")\n\nnumber = 0\nwith open(\"scores.csv\") as file:\n    for line in file:\n        parts = line.strip().split(\";\")\n        number += 1\n        print(f\"{number}. {parts[0]}: {parts[1]}\")\n","hints":["First append the new line with the mode `\"a\"`, then open the file again for reading. The second `open` sees the line you just added.","Read the file line by line, strip and split each line at `;`, and count the lines as you go.","Print each line as `f\"{number}. {parts[0]}: {parts[1]}\"`."],"tests":[{"name":"Test 1","stdin":"Cleo\n870\n","files":{"scores.csv":"Ana;950\nBo;720\n"},"writes":{"scores.csv":"Ana;950\nBo;720\nCleo;870\n"},"expect":"Name: Cleo\nScore: 870\n1. Ana: 950\n2. Bo: 720\n3. Cleo: 870","hidden":false},{"name":"Test 2","stdin":"Dee\n1200\n","files":{"scores.csv":"Eli;300\n"},"writes":{"scores.csv":"Eli;300\nDee;1200\n"},"expect":"Name: Dee\nScore: 1200\n1. Eli: 300\n2. Dee: 1200","hidden":true}],"require":[],"forbid":[]}]}