レシピ追加、ファイルをロックする
今日は「161:ファイルをロックする」を書いた 。ページは存在したのになぜか白紙だったのを昨日見つけたので。1年以上この状態だったのだけど放置されていた模様。
書いてて気づいたのは、ヘルプファイルの『Windows NT Files -- Locking』にあるコード例が正常動作しないという点。
import win32file import win32con import win32security import win32api import pywintypes highbits=0xffff0000 #high-order 32 bits of byte range to lock file="c:\\\\wilma.txt" secur_att = win32security.SECURITY_ATTRIBUTES() secur_att.Initialize() hfile=win32file.CreateFile(file, win32con.GENERIC_READ|win32con.GENERIC_WRITE, win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE, secur_att, #default win32con.OPEN_ALWAYS, win32con.FILE_ATTRIBUTE_NORMAL ,0) ov=pywintypes.OVERLAPPED() #used to indicate starting region to lock win32file.LockFileEx(hfile,win32con.LOCKFILE_EXCLUSIVE_LOCK,0,highbits,ov) win32api.Sleep(4000) #do something here win32file.UnlockFileEx(hfile,0,highbits,ov) hfile.Close()
LockFileEx の dwFileOffsetHigh 引数に 0xffff0000 を入れると 'OverflowError: long int too large to convert to int' になる。 0x7fffffff までなら入る。ここは DWORD のはずなのに (signed) int に直そうとしてしまっているのかな。当方環境は Python 2.5.4 , Windows XP 。 PyWin32 のバージョンは 252 。
PyWin32 が動かないならば ctypes の出番か?
from ctypes import windll, WINFUNCTYPE, POINTER, byref, Structure from ctypes.wintypes import BOOL, HANDLE, DWORD import win32file class OVERLAPPED(Structure): _fields_ = [ ('Internal', DWORD), ('InternalHigh', DWORD), ('Offset', DWORD), ('OffsetHigh', DWORD), ('hEvent', HANDLE), ] LockFileEx = WINFUNCTYPE( BOOL, HANDLE, DWORD, DWORD, DWORD, DWORD, POINTER(OVERLAPPED))( ('LockFileEx', windll.kernel32), ( (1, 'hFile)'), (1, 'dwFlags'), (1, 'dwReserved'), (1, 'nNumberOfBytesToLockLow'), (1, 'nNumberOfBytesToLockHigh'), (1, 'lpOverlapped'), ), ) UnlockFileEx = WINFUNCTYPE( BOOL, HANDLE, DWORD, DWORD, DWORD, POINTER(OVERLAPPED))( ('UnlockFileEx', windll.kernel32), ( (1, 'hFile)'), (1, 'dwReserved'), (1, 'nNumberOfBytesToLockLow'), (1, 'nNumberOfBytesToLockHigh'), (1, 'lpOverlapped'), ), ) def lock(fobj, flag=0): overlapped = OVERLAPPED() handle = win32file._get_osfhandle(fobj.fileno()) return LockFileEx( handle, flag, 0, 0, 0xffff0000, byref(overlapped)) def unlock(fobj): overlapped = OVERLAPPED() handle = win32file._get_osfhandle(fobj.fileno()) return UnlockFileEx( handle, 0, 0, 0xffff0000, byref(overlapped))