【问题标题】:Appending to the end of a file in a concurrent environment在并发环境中追加到文件的末尾
【发布时间】:2011-11-25 13:48:09
【问题描述】:

如果以下多个(示例)程序同时运行,需要采取哪些步骤来确保始终正确地将“完整”行附加到文件末尾。

#!/usr/bin/env python
import random
passwd_text=open("passwd.txt","a+")
u=("jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8917,(234)555-0077,jsmith@rosettacode.org:/home/jsmith:/bin/sh",
  "jdoe:x:1002:1000:Jane Doe,Room 1004,(234)555-8914,(234)555-0044,jdoe@rosettacode.org:/home/jdoe:/bin/sh",
  "xyz:x:1003:1000:X Yz,Room 1003,(234)555-8913,(234)555-0033,xyz@rosettacode.org:/home/xyz:/bin/sh")
for i in range(random.randint(1,2)):
  print >> passwd_text, random.choice(u)
passwd_text.close()

并且:即使磁盘已满或已设置“ulimit -f”,能否保证“全部或全部”附加(在 linux/unix 上)?

(注意类似问题:How do you append to a file?

【问题讨论】:

  • 我不知道如果磁盘已满,您如何追加数据...您可以在溢出的玻璃杯中添加更多的水吗?除此之外,使用文件锁。 flock() 是一个很好的起点。
  • @Marc B - re: "disk full" @... 好点,我看到 "write" 系统调用 "返回已写入的字节数。如果值为负数,则系统调用返回错误。”。我希望“umlimit -f”对“write”有同样的效果。因此,原子追加,可能 ½ 追加,但不能保证完整追加。 (我也不记得有任何 ioctl 保证“全部或全部”写入文件,即使“记录”很小)
  • 写入不是原子的吗?您的行可能与其他进程写入的其他行交错,但行本身应该是完整的,只要您最终使用单个 write 系统调用(os.write 应该保证,即使其他类型的写入可能是缓冲的)。如果您必须编写需要保持在一起的几行,请先将它们构建成一个字符串。
  • re:“写入不是原子的吗?” ...参照Linux NFS 概述、FAQ 和 HOWTO 文档 => nfs.sourceforge.net/#faq_a9 ...它似乎取决于操作系统和文件系统。 ¢ 这就是甲骨文支付如此丰厚股息的原因! :-) ¢

标签: python linux append


【解决方案1】:

我认为在 python 的普通 open 函数中对 this "bug" 的讨论表明你没有得到 POSIX 原子保证,但如果你使用的话,你会得到

with io.open('myfile', 'a') as f:
    f.write('stuff')

http://docs.python.org/2/library/io.html#io.open

如果操作系统正确地实现了它的 write sys 调用...

http://bugs.python.org/issue15723

【讨论】:

  • 所以你是说只要我使用 io.open 就没有理由使用 fctrl.flock ?
  • 我不知道你在做什么,所以我不能给你一个铁定的保证。但在我看来,如果您使用 io.open'a' 附加模式,您将获得 POSIX 原子写入保证。但是您应该阅读错误报告和相关链接,以确保它适用于您的用例。这里是龙。
  • 我只运行了多个脚本,它们可能随时想要更新文件中的某些内容。在这种情况下,我传统上会认为“你需要一个文件锁”,但有时 Python 比我预期的要聪明 :)
  • 我想强调的是,虽然据报道,如果操作正确,在适当的情况下,Windows 可以执行原子追加,但 Python 的 open()io.open() 不给你保证。
【解决方案2】:

您必须锁定文件以确保没有其他人同时写入。有关详细信息,请参阅 File Lockinglockfileposixfile

更新:如果磁盘已满,您将无法将更多数据写入文件。我不确定 Python 对输出重定向的实现,但write 系统调用可以写入比请求更少的字节数。

【讨论】:

  • 特别注意“man”页面提取专门处理 O_APPEND:如果设置了文件状态标志的 O_APPEND 标志,则文件偏移量应设置为每个之前的文件末尾在更改文件偏移量和写入操作之间不应发生写入和中间文件修改操作。
  • cf 这个讨论 - 看起来 python 的实现与 O_APPEND 预期的行为不完全匹配:bugs.python.org/issue15723
猜你喜欢
  • 2023-03-02
  • 2013-10-26
  • 2011-08-19
  • 1970-01-01
  • 2014-06-02
  • 1970-01-01
  • 1970-01-01
  • 2019-11-30
  • 2015-08-12
相关资源
最近更新 更多