Link to home
Start Free TrialLog in
Avatar of Vladimir Buzalka
Vladimir BuzalkaFlag for Czechia

asked on

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

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()
Avatar of ste5an
ste5an
Flag of Germany image

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.
Avatar of Vladimir Buzalka

ASKER

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
Avatar of noci
noci

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
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
Then there is some dangling reference in the win32com.client, which is not freed.
mail-parser looks ok too, just also needs perl. 
ASKER CERTIFIED SOLUTION
Avatar of Vladimir Buzalka
Vladimir Buzalka
Flag of Czechia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial