防止在 python 中创建文件

发布于 2024-10-30 18:44:28 字数 294 浏览 1 评论 0原文

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

提前致谢, 大卫

I'm working on a python server which concurrently handles transactions on a number of databases, each storing performance data about a different application. Concurrency is accomplished via the Multiprocessing module, so each transaction thread starts in a new process, and shared-memory data protection schemes are not viable.
I am using sqlite as my DBMS, and have opted to set up each application's DB in its own file. Unfortunately, this introduces a race condition on DB creation; If two process attempt to create a DB for the same new application at the same time, both will create the file where the DB is to be stored. My research leads me to believe that one cannot lock a file before it is created; Is there some other mechanism I can use to ensure that the file is not created and then written to concurrently?

Thanks in advance,
David

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

冷月断魂刀 2024-11-06 18:44:28

对于常规文件,处理此问题的常用 Unix 风格方法是尝试创建文件并查看它是否失败。在Python的情况下,那就是:

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

至少,您可以使用此方法尝试创建一个与数据库名称相似的“锁定文件”。如果创建了锁定文件,您可以继续创建数据库。如果没有,您可以针对“数据库存在”情况执行所需的操作。

The usual Unix-style way of handling this for regular files is to just try to create the file and see if it fails. In Python's case, that would be:

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

At the very least, you can use this method to try to create a "lock file" with a similar name to the database. If the lock file is created, you go ahead and make the database. If not, you do whatever you need to for the "database exists" case.

帅气称霸 2024-11-06 18:44:28

以保证它们不会冲突的方式命名数据库文件。

http://docs.python.org/library/tempfile.html

Name your database files in such a way that they are guaranteed not to collide.

http://docs.python.org/library/tempfile.html

酒解孤独 2024-11-06 18:44:28

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

You could capture the error when trying to create the file in your code and in your exception handler, check if the file exists and use the existing file instead of creating it.

枕头说它不想醒 2024-11-06 18:44:28

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

例如:fd = os.open(文件名, os.O_RDWR | os.O_CREAT | os.O_EXCL)

You didn't mention the platform, but on linux open(), or os.open() in python, takes a flags parameter which you can use. The O_CREAT flag creates a file if it does not exist, and the O_EXCL flag gives you an error if the file already exists. You'll also be needing O_RDONLY, O_WRONLY or O_RDWR for specifying the access mode. You can find these constants in the os module.

For example: fd = os.open(filename, os.O_RDWR | os.O_CREAT | os.O_EXCL)

数理化全能战士 2024-11-06 18:44:28

您可以使用 POSIX O_EXCLO_CREAT< /code> 标记为 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.

You can use the POSIX O_EXCL and O_CREAT flags to open(2) to guarantee that only a single process gets the file and thus the database; O_EXCL won't work over NFSv2 or earlier, and it'd be pretty shaky to rely on it for other network filesystems.

The liblockfile library implements a network-filesystem safe locking mechanism described in the open(2) manpage, which would be convenient; but I only see pre-made Ruby and Perl bindings. Depending upon your needs, maybe providing Python bindings would be useful, or perhaps just re-implementing the algorithm:

   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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文