Help: using msvcrt for file locking

Tim Peters tim.one at home.com
Sat Aug 25 23:25:42 EDT 2001


[Sheila King]
> I'm trying to do some file locking on Windows. I'm running Win98, but I
> hope that the methods in the msvcrt module will work OK on any win32?

msvcrt directly exposes some library functions supplied by, and unique to,
Microsoft.  So, like it or not (I don't like it myself <wink>), Microsoft is
the only entity who can answer questions about them with authority.  FWIW,
the docs MS supplied with MSVC 6 say their _locking function works under
"Win 95, Win NT", which *usually* means "everything after Win 3.1".

Also as usual, the functions MS provides as part of their C library are a
feeble subset of what you can do by using the Win32 API directly, in this
case by using the Win32 LockFile and LockFileEx functions.  I don't know
whether win32all exposes those specific functions; core Python does not.

> I thought I understood what I was doing. I had tested a bit of file
> locking stuff.
>
> I opened up two separate MSDOS console windows, and tried acquiring
> locks and releasing locks, etc...
>
> [seemingly successful stuff snipped]

> NOW, why doesn't this class that I've written work without error?
>
> Here is the class:
> ---------------(begin winLock module)--------------------
> ''' winLock.py
>
> class lockobject
> supports the same function calls as
> posixLock.lockobject
> export to lockobject.py: a wrapper module
> around the win and posix lockobjects
> '''
> import os, msvcrt
>
> modes = {'write':msvcrt.LK_RLCK, 'read':msvcrt.LK_NBLCK,\
>          'unlock':msvcrt.LK_UNLCK}
>
> class lockobject:
>     def _lockoperation(self, lockfilename, mode):
>         size = os.path.getsize(lockfilename)
>         f = open(lockfilename, 'r')
>         f.seek(0)
>         msvcrt.locking(f.fileno(), modes[mode], size)

My guess is that's why:  in your interactive sessions, you kept the file
open.  In the _lockoperation method above, the file will be closed
implicitly under CPython the instant _lockoperation returns (because the
refcount on f falls to 0 then, and an open file object is closed by the file
object's destructor).  The MS _locking docs say:

    Regions should be locked only briefly and should be unlocked before
    closing a file or exiting the program.

So if you leave locks sitting around when a file is closed, the behavior is
undefined.  I happen to get the same error from this program:

import os, msvcrt

NAME = 'empty.txt'

size = os.path.getsize(NAME)
f = open(NAME, 'r')
msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, size)

C:\Code\python\PCbuild>python mlock.py
Traceback (most recent call last):
  File "mlock.py", line 7, in ?
    msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, size)
IOError: [Errno 13] Permission denied

In other words, it's acting the same as if the file had never been locked.

> ...
> Now, why am I getting this Permission denied error?

The MS docs aren't clear, but what you're trying to do goes beyond even the
little they do say will work.

> ...
> (OK, I did put a seek(0) command in there. It didn't used to be there
> and I was getting the same error, so I though maybe I should set the
> file pointer to the beginning of the file each time?

The file pointer is always 0 immediately after an open for read, so the seek
wasn't needed; but it shouldn't hurt either.

> ...
> If someone can give me some tips here, I'd really appreciate it.

Cross-platform file-locking is extremely difficult, in part because Python
is coded in C and C defines no facilities for doing it.  I don't know why
you're trying to lock files, but the evidence suggests you're trying to use
msvcrt.locking for something it was never intended to do (it was intended
for programs like databases, where multiple threads and even processes
cooperatively both read and write to a single file, and sometimes need
exclusive access for brief periods of time to small regions of the file --
that's why there's a "size" argument).






More information about the Python-list mailing list