<jupyter_start><jupyter_text>Write and Save Files in PythonEstimated time needed: **25** minutes ObjectivesAfter completing this lab you will be able to:*   Write to files using Python libraries Table of Contents            Writing Files        Appending Files        Additional File modes        Copy a File     Writing Files We can open a file object using the method write() to save the text file to a list. To write to a file, the mode argument must be set to **w**. Let’s write a file **Example2.txt** with the line: **“This is line A”**<jupyter_code>exmp2 = 'Example2.txt'
f= open(exmp2,"x")
f.close()
    
# Write line to file
with open(exmp2, 'w') as writefile:
    writefile.write("This is line A")<jupyter_output><empty_output><jupyter_text>We can read the file to see if it worked:<jupyter_code># Read file

with open(exmp2, 'r') as testwritefile:
    print(testwritefile.read())<jupyter_output>This is line A<jupyter_text>We can write multiple lines:<jupyter_code># Write lines to file

with open(exmp2, 'w') as writefile:
    writefile.write("This is line A\n")
    writefile.write("This is line B\n")<jupyter_output><empty_output><jupyter_text>The method .write() works similar to the method .readline(), except instead of reading a new line it writes a new line. The process is illustrated in the figure. The different colour coding of the grid represents a new line added to the file after each method call.  You can check the file to see if your results are correct<jupyter_code># Check whether write to file

with open(exmp2, 'r') as testwritefile:
    print(testwritefile.read())<jupyter_output>This is line A
This is line B<jupyter_text>We write a list to a **.txt** file  as follows:<jupyter_code># Sample list of text

Lines = ["This is line A\n", "This is line B\n", "This is line C\n"]
Lines
# Write the strings in the list to text file

with open('Example2.txt', 'w') as writefile:
    for line in Lines:
        print(line)
        writefile.write(line)<jupyter_output>This is line A

This is line B

This is line C<jupyter_text>We can verify the file is written by reading it and printing out the values:<jupyter_code># Verify if writing to file is successfully executed

with open('Example2.txt', 'r') as testwritefile:
    print(testwritefile.read())<jupyter_output>This is line A
This is line B
This is line C<jupyter_text>However, note that setting the mode to **w** overwrites all the existing data in the file.<jupyter_code>with open('Example2.txt', 'w') as writefile:
    writefile.write("Overwrite\n")
with open('Example2.txt', 'r') as testwritefile:
    print(testwritefile.read())<jupyter_output>Overwrite<jupyter_text>Appending Files We can write to files without losing any of the existing data as follows by setting the mode argument to append: **a**.  you can append a new line as follows:<jupyter_code># Write a new line to text file

with open('Example2.txt', 'a') as testwritefile:
    testwritefile.write("This is line C\n")
    testwritefile.write("This is line D\n")
    testwritefile.write("This is line E\n")<jupyter_output><empty_output><jupyter_text>You can verify the file has changed by running the following cell:<jupyter_code># Verify if the new line is in the text file

with open('Example2.txt', 'r') as testwritefile:
    print(testwritefile.read())<jupyter_output>Overwrite
This is line C
This is line D
This is line E<jupyter_text>Additional modes  It's fairly ineffecient to open the file in **a** or **w** and then reopening it in **r** to read any lines. Luckily we can access the file in the following modes:*   **r+** : Reading and writing. Cannot truncate the file.*   **w+** : Writing and reading. Truncates the file.*   **a+** : Appending and Reading. Creates a new file, if none exists.You dont have to dwell on the specifics of each mode for this lab. Let's try out the **a+** mode:<jupyter_code>with open('Example2.txt', 'a+') as testwritefile:
    testwritefile.write("This is line E\n")
    print(testwritefile.read())<jupyter_output><jupyter_text>There were no errors but read() also did not output anything. This is because of our location in the file. Most of the file methods we've looked at work in a certain location in the file. .write()  writes at a certain location in the file. .read() reads at a certain location in the file and so on. You can think of this as moving your pointer around in the notepad to make changes at specific location. Opening the file in **w** is akin to opening the .txt file, moving your cursor to the beginning of the text file, writing new text and deleting everything that follows.Whereas opening the file in **a** is similiar to opening the .txt file, moving your cursor to the very end and then adding the new pieces of text. It is often very useful to know where the 'cursor' is in a file and be able to control it. The following methods allow us to do precisely this -*   .tell() - returns the current position in bytes*   .seek(offset,from) - changes the position by 'offset' bytes with respect to 'from'. From can take the value of 0,1,2 corresponding to beginning, relative to current position and end Now lets revisit **a+**<jupyter_code>with open('Example2.txt', 'a+') as testwritefile:
    print("Initial Location: {}".format(testwritefile.tell()))
    
    data = testwritefile.read()
    if (not data):  #empty strings return false in python
            print('Read nothing') 
    else: 
            print(testwritefile.read())
            
    testwritefile.seek(0,0) # move 0 bytes from beginning.
    
    print("\nNew Location : {}".format(testwritefile.tell()))
    data = testwritefile.read()
    if (not data): 
            print('Read nothing') 
    else: 
            print(data)
    
    print("Location after read: {}".format(testwritefile.tell()) )<jupyter_output>Initial Location: 59
Read nothing

New Location : 0
Overwrite
This is line C
This is line D
This is line E

Location after read: 59<jupyter_text>Finally, a note on the difference between **w+** and **r+**. Both of these modes allow access to read and write methods, however, opening a file in **w+** overwrites it and deletes all pre-existing data. To work with a file on existing data, use **r+** and **a+**. While using **r+**, it can be useful to add a .truncate() method at the end of your data. This will reduce the file to your data and delete everything that follows. In the following code block, Run the code as it is first and then run it with the .truncate().<jupyter_code>with open('Example2.txt', 'r+') as testwritefile:
    data = testwritefile.readlines()
    testwritefile.seek(0,0) #write at beginning of file
   
    testwritefile.write("Line 1" + "\n")
    testwritefile.write("Line 2" + "\n")
    testwritefile.write("Line 3" + "\n")
    testwritefile.write("finished\n")
    #Uncomment the line below
#     testwritefile.truncate()
    testwritefile.seek(0,0)
    print(testwritefile.read())<jupyter_output>Line 1
Line 2
Line 3
finished<jupyter_text>Copy a File  Let's copy the file **Example2.txt** to the file **Example3.txt**:<jupyter_code># Copy file to another

with open('Example2.txt','r') as readfile:
    with open('Example3.txt','w') as writefile:
          for line in readfile:
                writefile.write(line)<jupyter_output><empty_output><jupyter_text>We can read the file to see if everything works:<jupyter_code># Verify if the copy is successfully executed

with open('Example3.txt','r') as testwritefile:
    print(testwritefile.read())<jupyter_output>Line 1
Line 2
Line 3
finished
 line D
This is line E
This is line E<jupyter_text>After reading files, we can also write data into files and save them in different file formats like **.txt, .csv, .xls (for excel files) etc**. You will come across these in further examples Now go to the directory to ensure the **.txt** file exists and contains the summary data that we wrote.   Exercise  Your local university's Raptors fan club maintains a register of its active members on a .txt document. Every month they update the file by removing the members who are not active. You have been tasked with automating this with your Python skills. Given the file currentMem, Remove each member with a 'no' in their Active coloumn. Keep track of each of the removed members and append them to the exMem file. Make sure the format of the original files in preserved.   (*Hint: Do this by reading/writing whole lines and ensuring the header remains* ) Run the code block below prior to starting the exercise. The skeleton code has been provided for you, Edit only the cleanFiles function.<jupyter_code>#Run this prior to starting the exercise
from random import randint as rnd

memReg = 'members.txt'
exReg = 'inactive.txt'
fee =('yes','no')

def genFiles(current,old):
    with open(current,'w+') as writefile: 
        writefile.write('Membership No  Date Joined  Active  \n')
        data = "{:^13}  {:<11}  {:<6}\n"

        for rowno in range(20):
            date = str(rnd(2015,2020))+ '-' + str(rnd(1,12))+'-'+str(rnd(1,25))
            writefile.write(data.format(rnd(10000,99999),date,fee[rnd(0,1)]))


    with open(old,'w+') as writefile: 
        writefile.write('Membership No  Date Joined  Active  \n')
        data = "{:^13}  {:<11}  {:<6}\n"
        for rowno in range(3):
            date = str(rnd(2015,2020))+ '-' + str(rnd(1,12))+'-'+str(rnd(1,25))
            writefile.write(data.format(rnd(10000,99999),date,fee[1]))


genFiles(memReg,exReg)<jupyter_output><empty_output><jupyter_text>Start your solution below:<jupyter_code>def copy_file(old_file, new_file):
    with open(old_file,'r') as readfile:
        with open(new_file,'w') as writefile:
            for line in readfile:
                writefile.write(line)
                
copy_file("members.txt", "members_test.txt")
copy_file("inactive.txt", "inactive_test.txt")
with open("file.txt","r+") as f:
    new_f = f.readlines()
    f.seek(0)
    for line in new_f:
        if "snow" not in line:
            f.write(line)
    f.truncate()
def copy_file(old_file, new_file):
    with open(old_file,'r') as readfile:
        with open(new_file,'w') as writefile:
            for line in readfile:
                writefile.write(line)
                
copy_file("members.txt", "members_test.txt")
copy_file("inactive.txt", "inactive_test.txt")

def cleanFiles(current_mem,ex_mem):
    '''
    current_mem: File containing list of current members
    ex_mem: File containing list of old members
    
    Removes all rows from current_mem containing 'no' and appends them to ex_mem
    '''
    
    # gather list of current no's
    # remove no's from current_mem
    # append no's to ex_mem
    with open(current_mem, "r+") as f:
        with open(ex_mem, "a+") as ex_f:
            
            new_f = f.readlines()
            
            f.seek(0)
            f.truncate()
            print('truncate')
            for line in new_f:
                
                if "no" not in line:
                    #print('no', line)
                    f.write(line)
                else:
                    #print('yes', line)
                    ex_f.write(line)
            display(f.readlines())
            
            display(f.readlines())
            f.seek(0)
            print('f.seek(0)')
            display(f.readlines())
            print('f.seek(0)')


# Code to help you see the files
# Leave as is
def view_contents(memReg, exReg):



    headers = "Membership No  Date Joined  Active  \n"
    with open(memReg,'r') as readFile:
        print("Active Members: \n\n")
        print(readFile.read())

    with open(exReg,'r') as readFile:
        print("Inactive Members: \n\n")
        print(readFile.read())

        
cleanFiles('members_test.txt','inactive_test.txt')

print('BEFORE CLEANING')
view_contents('members.txt', 'inactive.txt')
print('AFTER CLEANING')
view_contents('members_test.txt','inactive_test.txt')<jupyter_output>truncate<jupyter_text>Run the following to verify your code:<jupyter_code>def testMsg(passed):
    if passed:
       return 'Test Passed'
    else :
       return 'Test Failed'

testWrite = "testWrite.txt"
testAppend = "testAppend.txt" 
passed = True

genFiles(testWrite,testAppend)

with open(testWrite,'r') as file:
    ogWrite = file.readlines()

with open(testAppend,'r') as file:
    ogAppend = file.readlines()

try:
    cleanFiles(testWrite,testAppend)
except:
    print('Error')

with open(testWrite,'r') as file:
    clWrite = file.readlines()

with open(testAppend,'r') as file:
    clAppend = file.readlines()
        
# checking if total no of rows is same, including headers

if (len(ogWrite) + len(ogAppend) != len(clWrite) + len(clAppend)):
    print("The number of rows do not add up. Make sure your final files have the same header and format.")
    passed = False
    
for line in clWrite:
    if  'no' in line:
        passed = False
        print("Inactive members in file")
        break
    else:
        if line not in ogWrite:
            print("Data in file does not match original file")
            passed = False
print ("{}".format(testMsg(passed)))<jupyter_output>Test Passed
{'fraction_non_alphanumeric': 0.10423179565383149, 'fraction_numerical': 0.008921082729698817, 'mean_word_length': 3.4325785738425143, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '17', 'dir': 'jupyter-structured-clean-dedup', 'id': '165889', 'license': 'Unlicense', 'n_tokens_mistral': 4086, 'n_tokens_neox': 3970, 'n_words': 1520, 'path': 'PY0101EN-4-2-WriteFile.ipynb', 'repo_name': 'jackruse/ibm-python', 'size': '13115'}