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

Comments: 发表评论



<< Home

This page is powered by Blogger. Isn't yours?