防止在python中创建文件

问题描述:

我正在使用一个python服务器,它同时处理多个数据库上的事务,每个数据库存储有关不同应用程序的性能数据。并发是通过多处理模块完成的,因此每个事务线程都在一个新进程中启动,并且共享内存数据保护机制不可行。 我使用sqlite作为我的数据库管理系统,并已选择在其自己的文件中设置每个应用程序的数据库。不幸的是,这引发了数据库创建的竞争条件;如果两个进程尝试同时为同一个新应用程序创建一个数据库,则两者都将创建要存储数据库的文件。我的研究让我相信,在创建文件之前无法锁定文件;有没有其他一些机制可以用来确保文件没有被创建,然后同时写入?防止在python中创建文件

由于提前,以这样的方式,他们保证不会碰撞 大卫

+0

也许我误解了,但不能只是重命名每个数据库的文件位置? – dfb 2011-04-05 23:16:33

通常的Unix风格的处理常规文件的方法是试图创建文件并查看它是否失败。在Python的情况下,这将是:

try: 
    os.open(filename, os.O_WRONLY | os.O_CREAT | os.O_EXCL) 
except IOError: # or OSError? 
    # Someone else created it already. 

最起码,你可以用这个方法来尝试创建一个“锁定文件”具有类似名称的数据库。如果创建了锁定文件,则继续制作数据库。如果没有,你可以为“数据库存在”情况做任何你需要的事情。

试图在代码中创建,并在您的异常处理程序中的文件,检查文件是否存在,而不是使用它创建现有的文件时,您可以捕获错误。

你没有提到这个平台,但是在linux上的open()os.open()在python中,需要一个你可以使用的flags参数。 O_CREAT标志创建一个文件,如果该文件不存在,并且O_EXCL标志给出错误(如果该文件已存在)。您还需要指定访问模式O_RDONLY,O_WRONLYO_RDWR。您可以在os模块中找到这些常量。

例如:fd = os.open(filename, os.O_RDWR | os.O_CREAT | os.O_EXCL)

您可以使用POSIX O_EXCL and O_CREAT flags to open(2)以保证只有一个单一的过程中获取文件,因此数据库; O_EXCL将无法​​通过NFSv2或更早的版本,并且将其用于其他网络文件系统依然不稳定。

liblockfile库实现了open(2)联机帮助页中描述的网络文件系统安全锁定机制,这很方便;但我只看到预先制作的Ruby和Perl绑定。根据您的需要,也许提供Python绑定将是有用的,或者可能只是重新实现算法:

O_EXCL Ensure that this call creates the file: if this flag is 
      specified in conjunction with O_CREAT, and pathname 
      already exists, then open() will fail. The behavior of 
      O_EXCL is undefined if O_CREAT is not specified. 

      When these two flags are specified, symbolic links are not 
      followed: if pathname is a symbolic link, then open() 
      fails regardless of where the symbolic link points to. 

      O_EXCL is only supported on NFS when using NFSv3 or later 
      on kernel 2.6 or later. In environments where NFS O_EXCL 
      support is not provided, programs that rely on it for 
      performing locking tasks will contain a race condition. 
      Portable programs that want to perform atomic file locking 
      using a lockfile, and need to avoid reliance on NFS 
      support for O_EXCL, can create a unique file on the same 
      file system (e.g., incorporating hostname and PID), and 
      use link(2) to make a link to the lockfile. If link(2) 
      returns 0, the lock is successful. Otherwise, use stat(2) 
      on the unique file to check if its link count has 
      increased to 2, in which case the lock is also successful.