2007-08-01
Python Cookbook 2.28 使用跨平台API锁定文件
需求:
你需要在一个程序中锁定文件,而此程序又可以同时运行在Windows和类Uiux系统上,但是Python标准库并没有提供通用的函数来实现这个功能,只有特定平台的库提供相关函数.
讨论:
当Python标准库没有提供跨平台解决方案的时候,通常需要我们自己写一个:
import os
# needs win32all to work on Windows (NT, 2K, XP, _not_ /95 or /98)
if os.name == 'nt':
import win32con, win32file, pywintypes
LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
LOCK_SH = 0 # the default
LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
_ _overlapped = pywintypes.OVERLAPPED( )
def lock(file, flags):
hfile = win32file._get_osfhandle( file.fileno( ))
win32file.LockFileEx(hfile, flags, 0, 0xffff0000, _ _overlapped)
def unlock(file):
hfile = win32file._get_osfhandle(file.fileno( ))
win32file.UnlockFileEx(hfile, 0, 0xffff0000, _ _overlapped)
elif os.name == 'posix':
from fcntl import LOCK_EX, LOCK_SH, LOCK_NB
def lock(file, flags):
fcntl.flock(file.fileno( ), flags)
def unlock(file):
fcntl.flock(file.fileno( ), fcntl.LOCK_UN)
else:
raise RuntimeError("PortaLocker only defined for nt and posix platforms")
当多个程序或线程访问共享文件时,需要保证操作是同步的,否则两个进程可能同时去修改一个文件.同步操作的失败有可能导致文件的损害.
本节提供了两个函数:lock和unlock,分别用于给文件加锁和解锁.使用portalock.py模块很简单 ,只要调用lock方法,并将文件名和锁类型做为参数就可以了:
共享锁(Shared Lock,默认)
这种锁拒绝所有进程的写操作,包括加锁的进程.所有的进程都可以进行读操作.
排它锁(Exclusive Lock)
这种锁拒绝别的进程读或者写文件.
非阻塞锁(Nonblocking Lock)
当该值被设定时,函数如果发现不能应用要求加的锁,就立刻返回,否则就等待.LOCK_NB 可以进行或操作,可以是LOCK_SH或LOCK_EX.
举例说明:
import portalocker
afile = open("somefile", "r+")
portalocker.lock(afile, portalocker.LOCK_EX)
不同的操作系统对文件锁的实现是完全不同的.在类Unix系统上(包括Linux 和Mac OS),上面的代码依赖fcntl库中的函数,而在Windows平台上(2000,NT,XP),它使用win32file模块, 是PyWin32扩展的一部分.但是重点是,不考虑平台无关性,代码中访问系统的方式和你传递的参数(flags)都是一样的.这些跨平台包虽然实现不同,可是却能方便利用于写跨平台程序,这也是Python的优点之一.
当你写跨平台程序时,比较好的方式是封装你的操作.就文件加锁来说,对于那些需要使用跨平台lock操作的用户,是非常有用的.更一般的情况,if os.name==这样的语句不应该是应用程序级别的代码,它应该处于标准库或者独立于应用程序的模块中,如本节的代码.
相关说明:
本节所演示的代码就是portalocker.py
你需要在一个程序中锁定文件,而此程序又可以同时运行在Windows和类Uiux系统上,但是Python标准库并没有提供通用的函数来实现这个功能,只有特定平台的库提供相关函数.
讨论:
当Python标准库没有提供跨平台解决方案的时候,通常需要我们自己写一个:
import os
# needs win32all to work on Windows (NT, 2K, XP, _not_ /95 or /98)
if os.name == 'nt':
import win32con, win32file, pywintypes
LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
LOCK_SH = 0 # the default
LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
_ _overlapped = pywintypes.OVERLAPPED( )
def lock(file, flags):
hfile = win32file._get_osfhandle( file.fileno( ))
win32file.LockFileEx(hfile, flags, 0, 0xffff0000, _ _overlapped)
def unlock(file):
hfile = win32file._get_osfhandle(file.fileno( ))
win32file.UnlockFileEx(hfile, 0, 0xffff0000, _ _overlapped)
elif os.name == 'posix':
from fcntl import LOCK_EX, LOCK_SH, LOCK_NB
def lock(file, flags):
fcntl.flock(file.fileno( ), flags)
def unlock(file):
fcntl.flock(file.fileno( ), fcntl.LOCK_UN)
else:
raise RuntimeError("PortaLocker only defined for nt and posix platforms")
当多个程序或线程访问共享文件时,需要保证操作是同步的,否则两个进程可能同时去修改一个文件.同步操作的失败有可能导致文件的损害.
本节提供了两个函数:lock和unlock,分别用于给文件加锁和解锁.使用portalock.py模块很简单 ,只要调用lock方法,并将文件名和锁类型做为参数就可以了:
共享锁(Shared Lock,默认)
这种锁拒绝所有进程的写操作,包括加锁的进程.所有的进程都可以进行读操作.
排它锁(Exclusive Lock)
这种锁拒绝别的进程读或者写文件.
非阻塞锁(Nonblocking Lock)
当该值被设定时,函数如果发现不能应用要求加的锁,就立刻返回,否则就等待.LOCK_NB 可以进行或操作,可以是LOCK_SH或LOCK_EX.
举例说明:
import portalocker
afile = open("somefile", "r+")
portalocker.lock(afile, portalocker.LOCK_EX)
不同的操作系统对文件锁的实现是完全不同的.在类Unix系统上(包括Linux 和Mac OS),上面的代码依赖fcntl库中的函数,而在Windows平台上(2000,NT,XP),它使用win32file模块, 是PyWin32扩展的一部分.但是重点是,不考虑平台无关性,代码中访问系统的方式和你传递的参数(flags)都是一样的.这些跨平台包虽然实现不同,可是却能方便利用于写跨平台程序,这也是Python的优点之一.
当你写跨平台程序时,比较好的方式是封装你的操作.就文件加锁来说,对于那些需要使用跨平台lock操作的用户,是非常有用的.更一般的情况,if os.name==这样的语句不应该是应用程序级别的代码,它应该处于标准库或者独立于应用程序的模块中,如本节的代码.
相关说明:
本节所演示的代码就是portalocker.py