Question

My medical office has a network drive (run off a DLink-325 NAS, if that makes any difference) which holds all the documents for our patients. Each patient has a folder with their name, and each folder holds those documents. The problem is that the Windows file explorer is not well suited to this sort of situation - users can accidentally rename folders (throwing off the sort), move patient folders, etc. So, I'm working on developing a python app (built on django for the web interface) and I'm to the point where I need to make sure the django database matches with the file system so that whenever something does change with the file/folder names, the database points to the correct files. I read Tim Golden's article and thought that would be an excellent solution. And it was - as long as I was testing it on local folders. However, as soon as I pointed it to the network drive, I ran into this strange error:

Traceback (most recent call last):   File "C:\projects\RecordKeeper\test.py", line 50, in <module>
    None pywintypes.error: (58, 'ReadDirectoryChangesW', 'The specified server cannot perform the requested operation.') [Finished in 16.4s]

Oddly enough, this only happens when the file name is changed to something new. If I change the file name, then change it back, everything works perfectly.

For instance, if the original file name is "Referral.pdf" and I change it to "Raferral.pdf" (just changed the "e" to an "a"), I get the error. However, if I change it back to "Referral.pdf", I get the proper output. Here is my code (I've changed the folder name to protect patient health information):

import os

import win32file
import win32con

ACTIONS = {
  1 : "Created",
  2 : "Deleted",
  3 : "Updated",
  4 : "Renamed from something",
  5 : "Renamed to something"
}
# Thanks to Claudio Grondi for the correct set of numbers
FILE_LIST_DIRECTORY = 0x0001

#path_to_watch = "C:\projects\working"
path_to_watch = "Z:\_Charts\Abruzzo, Sandra J - 1947-11-18"
hDir = win32file.CreateFile (
  path_to_watch,
  FILE_LIST_DIRECTORY,
  win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE | win32con.FILE_SHARE_DELETE,
  None,
  win32con.OPEN_EXISTING,
  win32con.FILE_FLAG_BACKUP_SEMANTICS,
  None
)
while 1:
  #
  # ReadDirectoryChangesW takes a previously-created
  # handle to a directory, a buffer size for results,
  # a flag to indicate whether to watch subtrees and
  # a filter of what changes to notify.
  #
  # NB Tim Juchcinski reports that he needed to up
  # the buffer size to be sure of picking up all
  # events when a large number of files were
  # deleted at once.
  #
  try:
    results = win32file.ReadDirectoryChangesW (
      hDir,
      1024,
      True,
      win32con.FILE_NOTIFY_CHANGE_FILE_NAME |
       win32con.FILE_NOTIFY_CHANGE_DIR_NAME |
       win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES |
       win32con.FILE_NOTIFY_CHANGE_SIZE |
       win32con.FILE_NOTIFY_CHANGE_LAST_WRITE |
       win32con.FILE_NOTIFY_CHANGE_SECURITY,
      None,
      None
    )
    for action, file in results:
      full_filename = os.path.join (path_to_watch, file)
      print full_filename, ACTIONS.get (action, "Unknown")
  except Exception as e:
    print "Unexpected error:", e

UPDATE

I added try/catch block to the code above to troubleshoot this problem a little more. It seems just the renaming stuff that's causing a problem. It still can tell if the file was updated. Here's the output I got during one test:

Z:\_Charts\Abruzzo, Sandra J - 1947-11-18\2013-06-12 Request for records.pdf Renamed from something
Z:\_Charts\Abruzzo, Sandra J - 1947-11-18\2013-06-12 Requeast for records.pdf Renamed to something
Z:\_Charts\Abruzzo, Sandra J - 1947-11-18\2013-06-12 Requeast for records.pdf Updated
Unexpected error: (58, 'ReadDirectoryChangesW', 'The specified server cannot perform the requested operation.')
Z:\_Charts\Abruzzo, Sandra J - 1947-11-18\2013-06-12 Request for records.pdf Updated

As you can see, it handled the first rename with no problem. But when I tried to rename it back, the rename operation threw an error, but the update notification worked perfectly fine. Anyone have any ideas given these new wrinkles?

UPDATE

I think I've figured out a solution. As many users have said, actually getting accurate data from the network drive all the time is not going to happen. However, the program did at least report every time a file was updated, even if it threw an error when getting the rename data. So, I wrote several special methods that went through the database, found records that no longer pointed to valid files, and updated those records. Hopefully that will do it. If anyone has a better solution, please feel free to share! :D

Was it helpful?

Solution

According to this blog, NAS devices typically do not support the required functionality to support the ReadDirectoryChangesW function, so it sounds like the problem is with your drive, not your python code. This accompanying page mentions a couple of other functions which offer similar functionality and their various pros and cons, but doesn't go into details such as whether they work over network drives.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top