Search code examples
pythonpyramid

Read lines from a txt. file and write all except 6 first lines on another, then flush the first file


I'm trying to create a Python code that reads data from an email, saves it onto a temporary txt. file. There will be another permanent txt. file, where the temporary txt. files contents will be written in a form that skips the first 6 lines. During this loop the temporary file gets flushed, so the same data will not be written multiple times.

Here is the code I have worked with:

for part in email_message.walk():
    if part.get_content_type() == 'text/plain':
        body = part.get_payload(decode=True)
        save_string = str('C:/Email/file.txt')
        myfile = open(save_string, 'a')
        myfile.write(str(body)) ## Write to file 2 and then flush this 
        open ('C:/Email/file.txt','w+') as f:
        lines = f.readlines()
        open ('C:/Email/newfile.txt','a') as g:
        g.writelines(lines[6:])
        f.close()
        g.close()
        myfile.close()# Clear first file 
    else:
        continue

Currently the issue is that it writes the email to the first txt. file, but does not update the second txt. file. However, when I run the code again, the previous data gets written to the second txt. This is something I don't quite understand why it happens, since the order should be correct. Thanks in advance!

More of the code here:

@view_config(route_name='update-data')
def update_view(request):

    m = imaplib.IMAP4_SSL('imap.gmail.com')
    m.login('gmail@gmail.com', 'password')
    m.list()
    m.select('inbox')

    result, data = m.uid('search', None, 'UNSEEN') # Only unseen mail
    
    i = len(data[0].split()) #space separate string
    
    if i == 0:
        return Response('<h3> Data cannot be updated </h3><h4>No new emails</h4><a href="localhost:8888"> Return to the main page </a> ')
    
    for x in range(i):
        latest_email_uid = data[0].split()[x]
        result, email_data = m.uid('fetch', latest_email_uid, '(RFC822)')
        raw_email = email_data[0][1]
        raw_email_string = raw_email.decode('utf-8')
        email_message = email.message_from_string(raw_email_string)

        
        
        for part in email_message.walk():
            if part.get_content_type() == 'text/plain':
                body = part.get_payload(decode=True)
                save_string = str('C:/Email/file.txt')
                myfile = open(save_string, 'a')
                myfile.write(str(body)) ## Write to file 2 and then flush this 
                open ('C:/Email/file.txt','w+') as f:
                lines = f.readlines()
                open ('C:/Email/newfile.txt','a') as g:
                g.writelines(lines[6:])
                f.close()
                g.close()
                myfile.close()# Clear first file 
            else:
                continue
                

                
                
            return Response('<h3>Data update successful</h3>')

EDIT

Got it working the way I want with this:

for part in email_message.walk():
    if part.get_content_type() == 'text/plain':
        body = part.get_payload(decode=True)
        with open('C:/Email/file.txt', 'a') as myfile:  # Opens file.txt and writes the email body
            myfile.write(str(body)) 
        with open('C:/Email/file.txt', 'r+') as f:  # Opens file.txt again in read mode and reads lines
            lines = f.readlines()
            with open ('C:/Email/newfile.txt','a') as g: # Writes file.txt contents to newfile.txt, starting from line 6, deletes contents of the first file
                g.writelines(lines[6:])
                f.truncate(0)
    else:
        continue

Solution

  • You need to close myfile before trying to reopen it and you should reopen it in read mode. Try something like this

    
    for part in email_message.walk():
        if part.get_content_type() == 'text/plain':
            body = part.get_payload(decode=True)
            save_string = str('C:/Email/file.txt')
            myfile = open(save_string, 'a')
            myfile.write(str(body)) ## Write to file 2 and then flush this 
            myfile.close()
            open ('C:/Email/file.txt','r') as f:
            lines = f.readlines()
            open ('C:/Email/newfile.txt','a') as g:
            g.writelines(lines[6:])
            f.close()
            g.close()
    

    But it would be better to use with context manager to open your files, in which case you dont have to worry about closing files

    for part in email_message.walk():
        if part.get_content_type() == 'text/plain':
            body = part.get_payload(decode=True)
            with open('C:/Email/file.txt', 'a') as myfile:
                myfile.write(str(body)) 
            with open('C:/Email/file.txt', 'r') as f:
                lines = f.readlines()
                with open ('C:/Email/newfile.txt','a') as g:
                    g.writelines(lines[6:])