We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Cannot delete file in Python, it is used by another process.

Medium Priority
60 Views
Last Modified: 2020-06-25
Dear Experts,

I have python code to:
1. retrieve stored MSG email from MongoDB and save it to disk
2. open that stored MSG email via outlook
3. read several things from file
4. close that outlook message
5. delete disk from disk

I am receiving error on os.remove(filename) with error message
Traceback (most recent call last):
  File "Z:/Dropbox/#Python/PyCharm/ReadMongo.py", line 71, in <module>
    os.remove(filename)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'z:\\00000000B229A92B98C6E7479C47B8AA566FF2C9E4842C00.msg'

But I do not know how to release that file.

I believe I am correctly closing outlook mailitem via postovnizprava.close(1)  - argument 1 being DISCARD

Can you advice please or give me any idea to work on?

Thanks

Vladimir

Full code is here:
import time
import pymongo
import os
import gridfs
from bson.objectid import ObjectId
import sys
import win32com.client

# tento proptag zjisti charakter prilohy
PR_ATTACH_CONTENT_ID = "http://schemas.microsoft.com/mapi/proptag/0x3712001F"

# tento proptag zjisti message headers
TransportMessageHeadersSchema = "http://schemas.microsoft.com/mapi/proptag/0x007D001E"

outlookmapi = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")

myclient = pymongo.MongoClient("mongodb://192.168.1.76:27017/")
print(myclient.list_database_names())
mydb = myclient["db_emailu"]
print(mydb.name)
fs=gridfs.GridFS(mydb)
fsat=gridfs.GridFS(mydb,"attachments")

nalez=mydb["fs.files"].find({}).limit(1)

for s in nalez:
    print(s["entryid"])
    filename="z:\\"+s["entryid"]+".msg"
    soubor=fs.get(s["_id"]).read()
    newFile=open(filename,"wb")
    newFile.write(soubor)
    newFile.close()

    postovnizprava=outlookmapi.openshareditem(filename)
    # postovnizprava.display()
    for at in postovnizprava.attachments:
      print(at.filename,at.propertyaccessor.getproperty(PR_ATTACH_CONTENT_ID)=="")
      if at.propertyaccessor.getproperty(PR_ATTACH_CONTENT_ID)=="":
        atFileName="z:\\"+at.filename
        at.saveasfile(atFileName)
        atFile=open(atFileName,"rb")
        fsat.put(atFile.read(),filename=at.filename,entryid=s["entryid"])
        atFile.close()
        os.remove(atFileName)

    InsertDic={}
    InsertDic["entryid"]=s["entryid"]
    InsertDic["subject"] = postovnizprava.subject
    InsertDic["sendername"] = postovnizprava.sendername
    InsertDic["senderemailaddress"] = postovnizprava.senderemailaddress
    InsertDic["to"] = postovnizprava.to
    InsertDic["cc"] = postovnizprava.cc
    InsertDic["bcc"] = postovnizprava.bcc
    InsertDic["categories"] = postovnizprava.categories
    InsertDic["receivedtime"] = postovnizprava.receivedtime
    InsertDic["sent"] = postovnizprava.sent
    InsertDic["senton"] = postovnizprava.senton
    InsertDic["bodyformat"] = postovnizprava.bodyformat
    InsertDic["body"] = postovnizprava.body
    InsertDic["htmlbody"] = postovnizprava.htmlbody
    InsertDic["rtfbody"] = bytes(postovnizprava.rtfbody)
    InsertDic["importance"] = postovnizprava.importance
    InsertDic["headers"] = postovnizprava.propertyaccessor.getproperty(TransportMessageHeadersSchema)
    x=mydb["emails"].insert_one(InsertDic)

    print(postovnizprava.entryid)
    print(filename)
    postovnizprava.close(1)
    postovnizprava=None
    print(type(postovnizprava))
    os.remove(filename)


sys.exit()
Comment
Watch Question

ste5anSenior Developer
CERTIFIED EXPERT
It looks okay at the first glance, so when there is no pitfall I'm not aware of, you need to consider, that closing an application like Outlook requires time.
And I'm pretty sure that this method is not 100% sequential/blocking, thus I suspect you reach the remove() call before everything is really closed.

Just try a time.sleep(1) or some more seconds.
Dear Ste5an

it does not work, I added time.sleep(20) and error is the same. But when script finishes with error, and I switch to file explorer, I can simply delete file, it is not kept by any process anymore.

Advice?

Many thanks

Vladimir
nociSoftware Engineer
CERTIFIED EXPERT
Distinguished Expert 2019
Maybe a mail message parser is a better solution then start out of control other processes to read part from a message:

https://pypi.org/project/eml-parser/
https://pypi.org/project/EmailParser/

Basically msg file are just text files. (should be..., as all data is supposed to be ascii).
Dear noci

I have probably found even better parser  https://pypi.org/project/mail-parser/ 

It seems to be able to process file received from mondo directly from memory, without need to store it as file. I will check.

Hopefully I will be able to extract all properties I need.

Thanks

Vladimir
CERTIFIED EXPERT
My experience is that Outlook sometimes locks the file longer than it should (někdy je to na posrání). Did you try to close Outlook first and then to delete the file (using the script)?
Dear Pepr,

it is unbelievable, but closing outlookapplication.quit() + even another 5 seconds of sleep  does not help :-(((((

Thanks
V
ste5anSenior Developer
CERTIFIED EXPERT
Then there is some dangling reference in the win32com.client, which is not freed.
nociSoftware Engineer
CERTIFIED EXPERT
Distinguished Expert 2019
mail-parser looks ok too, just also needs perl. 
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.