防止在 python 中创建文件
我正在开发一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
对于常规文件,处理此问题的常用 Unix 风格方法是尝试创建文件并查看它是否失败。在Python的情况下,那就是:
至少,您可以使用此方法尝试创建一个与数据库名称相似的“锁定文件”。如果创建了锁定文件,您可以继续创建数据库。如果没有,您可以针对“数据库存在”情况执行所需的操作。
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:
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.
以保证它们不会冲突的方式命名数据库文件。
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
当尝试在代码和异常处理程序中创建文件时,您可以捕获错误,检查文件是否存在并使用现有文件而不是创建它。
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.
您没有提到平台,但在 linux
open()
上,或 python 中的os.open()
上,采用您可以使用的 flags 参数。如果文件不存在,O_CREAT
标志会创建一个文件;如果文件已存在,O_EXCL
标志会给出错误。您还需要O_RDONLY
、O_WRONLY
或O_RDWR
来指定访问模式。您可以在 os 模块中找到这些常量。例如:fd = os.open(文件名, os.O_RDWR | os.O_CREAT | os.O_EXCL)
You didn't mention the platform, but on linux
open()
, oros.open()
in python, takes a flags parameter which you can use. TheO_CREAT
flag creates a file if it does not exist, and theO_EXCL
flag gives you an error if the file already exists. You'll also be needingO_RDONLY
,O_WRONLY
orO_RDWR
for specifying the access mode. You can find these constants in theos
module.For example:
fd = os.open(filename, os.O_RDWR | os.O_CREAT | os.O_EXCL)
您可以使用 POSIX
O_EXCL
和O_CREAT< /code> 标记为
open(2)
以保证只有一个进程获取文件,从而获取数据库;
O_EXCL
无法在 NFSv2 或更早版本上工作,并且依赖它来实现其他网络文件系统会非常不稳定。liblockfile
库实现了网络文件系统安全锁定机制,描述于open(2)
联机帮助页,这会很方便;但我只看到预制的 Ruby 和 Perl 绑定。根据您的需求,也许提供 Python 绑定会很有用,或者可能只是重新实现算法:You can use the POSIX
O_EXCL
andO_CREAT
flags toopen(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 theopen(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: