如果我从 python 中的多个不同进程登录到同一个文件,会发生什么?

2024-05-06

我花了几个小时来挖掘这种行为,首先是关于这些问题:

  • `write(2)` 到本地文件系统的原子性 https://stackoverflow.com/questions/10650861/atomicity-of-write2-to-a-local-filesystem
  • 如何同步(使原子化)从两个进程写入一个文件? https://stackoverflow.com/questions/6896011/how-can-i-synchronize-make-atomic-writes-on-one-file-from-from-two-process
  • 如何以编程方式确定“写入”系统调用对特定文件是否是原子的? https://stackoverflow.com/questions/7660293/how-does-one-programmatically-determine-if-write-system-call-is-atomic-on-a-pa
  • 如果两个不同的进程同时对同一文件调用写入系统调用,会发生什么情况 https://stackoverflow.com/questions/7236475/what-happens-if-a-write-system-call-is-called-on-same-file-by-2-different-proces
  • http://article.gmane.org/gmane.linux.kernel/43445 http://article.gmane.org/gmane.linux.kernel/43445

看来如果我们在打开文件时使用“O_APPEND”标志,那么在 Linux 上从多个进程登录到同一个文件总是可以的。我相信 python 肯定在其日志记录模块中使用“O_APPEND”标志。

从一个小测试来看:

#!/bin/env python
import os
import logging

logger = logging.getLogger('spam_application')
logger.setLevel(logging.DEBUG)
# create file handler which logs even debug messages
fh = logging.FileHandler('spam.log')
logger.addHandler(fh)
formatter = logging.Formatter(
    '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)

for i in xrange(10000):
    p = os.getpid()
    logger.debug('Log line number %s in %s', i, p)

我运行它:

./test.py & ./test.py & ./test.py & ./test.py &

我发现spam.log没有任何问题。这种行为或许可以支持上面的结论。

但问题随之而来:

  • 这是什么意思here https://docs.python.org/2/howto/logging-cookbook.html#logging-to-a-single-file-from-multiple-processes?
  • 以及使用场景有哪些this https://pypi.python.org/pypi/ConcurrentLogHandler/0.9.1,只是为了文件轮换?

最后,如果两个进程正在同一个文件上进行写入,我的意思是它们正在同一个文件上调用 write(2),谁确保来自两个进程的数据不会交错(内核或文件系统?),以及如何交错。[注意:我只是想深入了解 write 系统调用,欢迎任何有关此的点击。]

EDIT1 :

Do this https://docs.python.org/2/howto/logging-cookbook.html#logging-to-a-single-file-from-multiple-processes and this https://pypi.python.org/pypi/ConcurrentLogHandler/0.9.1只是为了不同操作系统环境(如 Windows、Linux 或 Mac)之间的兼容性而存在?

EDIT2 :

再进行一项测试,每次向logging.debug提供8KB字符串。这次我可以在 spam.log 中看到“交错”行为。 此行为正是上面一页中有关 PIPE_BUF 的指定内容。所以看起来 Linux 上的行为很清楚,如果 write(2) 的大小小于 PIPE_BUF,则使用 O_APPEND 是可以的。


我越挖越深。现在我想这些事实已经很清楚了:

  1. 使用 O_APPEND,多个进程的并行 write(2) 就可以了。只是行的顺序未确定,但行不会相互交错或覆盖。根据尼尔·道格拉斯 (Niall Douglas) 的回答,数据的大小是任意数量的了解多个进程的并发文件写入 https://stackoverflow.com/questions/12942915/understanding-concurrent-file-writes-from-multiple-processes。我已经在linux上对此进行了“任意数量”的测试,但没有找到上限,所以我想这是正确的。

  2. 没有O_APPEND,就会乱七八糟。 POSIX 是这样说的:“POSIX.1-2008 的本卷没有指定从多个进程并发写入文件的行为。应用程序应该使用某种形式的并发控制。”

  3. 现在我们进入Python。我在 EDIT3 中进行的测试,即 8K,我找到了它的起源。 Python的write()实际上使用了fwrite(3),而我的python在这里设置了一个BUFF_SIZE,即8192。根据abarnert的回答Linux 上文件的默认缓冲区大小 https://stackoverflow.com/questions/18194374/default-buffer-size-for-a-file。这个8192的故事说来话长。

不过,欢迎提供更多信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果我从 python 中的多个不同进程登录到同一个文件,会发生什么? 的相关文章

  • 从 Python 中的 message_from_string() 获取发件人地址

    有人可以告诉我如何在Python中从email message from string 获取发件人地址吗 谢谢 我试过 message email message from string email text from message Fr
  • setColumnStretch 和 setRowStretch 如何工作

    我有一个使用构建的应用程序PySide2它使用setColumnStretch用于柱拉伸和setRowStretch用于行拉伸 它工作得很好 但我无法理解它是如何工作的 我参考了 qt 文档 但它对我没有帮助 我被困在括号内的两个值上 例如
  • 使用 pyppeteer 与 asyncio 关联来抓取内容

    我用 python 结合编写了一个脚本pyppeteer随着asyncio从其登陆页面抓取不同帖子的链接 并最终通过跟踪通向其内页的 url 来获取每个帖子的标题 我这里解析的内容不是动态的 但是 我利用了pyppeteer and asy
  • 如何进行重定向并保留查询字符串?

    我想进行重定向并保留查询字符串 就像是self redirect加上发送的查询参数 那可能吗 newurl my new route urllib urlencode self request params self redirect ne
  • 关于具有自定义损失的 3 输出 ANN 的加权

    我正在尝试定义一个自定义损失函数 它在回归模型中接收 3 个输出变量 def custom loss y true y pred y true c K cast y true float32 Shape batch size 3 y pre
  • 熊猫系列到二维数组

    所以 我使用了来自的答案将二维数组放入 Pandas 系列中 https stackoverflow com questions 38840319 put a 2d array into a pandas series将 2D numpy
  • 如何使用 Python 在表单中选择选项?

    我想知道如何以格式如下的形式选择选项 td align left td
  • 如何在 tkinter 后台运行函数[重复]

    这个问题在这里已经有答案了 我是 GUI 编程新手 我想用 tkinter 编写一个 Python 程序 我想要它做的就是在后台运行一个可以通过 GUI 影响的简单函数 该函数从 0 计数到无穷大 直到按下按钮为止 至少这是我想要它做的 但
  • 如何在使用 Flask for Python 3 的同时使用 Bootstrap 4?

    我检查过 发现默认安装时 Flask Bootstrap 原生使用 Bootstrap 3 3 7 但实际上我想通过使用 Flask Bootstrap 包在我的项目中使用 Bootstrap 4 任何有关如何更新它或类似内容的帮助将不胜感
  • 使用张量流导出神经网络的权重

    我使用张量流工具编写了神经网络 一切正常 现在我想导出神经网络的最终权重以制定单一的预测方法 我怎样才能做到这一点 您需要在训练结束时使用以下命令保存模型tf train Saver https www tensorflow org ver
  • Pandas 根据条件替换数据框值

    我有一个主数据框 df Colour Item Price Blue Car 40 Red Car 30 Green Truck 50 Green Bike 30 然后我有一个价格修正数据框 df pc Colour Item Price
  • PySpark DataFrame 上分组数据的 Pandas 式转换

    如果我们有一个由一列类别和一列值组成的 Pandas 数据框 我们可以通过执行以下操作来删除每个类别中的平均值 df DemeanedValues df groupby Category Values transform lambda g
  • Python:如何“杀死”类实例/对象?

    我希望 Roach 类在达到一定量的 饥饿 时 死亡 但我不知道如何删除该实例 我的术语可能有误 但我的意思是 窗户上有大量 蟑螂 我希望特定的蟑螂完全消失 我会向您展示代码 但它很长 我将蟑螂类添加到策划者类蟑螂种群列表中 一般来说 每个
  • 从 SUDS 中的 SOAP 响应中提取 Cookie

    我必须使用具有多种服务的 API 所有这些都需要来自下面的身份验证的 JSESSION cookie 然而 当我调用下一个服务时 它不会保留 cookie 因此会拒绝它们 from suds client import Client url
  • 从函数在 python 3 中创建全局变量

    我想知道为什么在函数结束后我无法访问变量 variable for raw data 代码是这样的 def htmlfrom Website URL import urllib request response urllib request
  • python 中“重载”函数的最佳方法? [复制]

    这个问题在这里已经有答案了 我正在尝试在 python 中做这样的事情 def foo x y do something at position x y def foo pos foo pos x pos y 所以我想根据我提供的参数数量调
  • 如何将另一整列作为参数传递给 pandas fillna()

    我想用另一列中的值填充一列中的缺失值 使用fillna方法 我读到循环遍历每一行将是非常糟糕的做法 最好一次完成所有事情 但我不知道如何使用fillna 之前的数据 Day Cat1 Cat2 1 cat mouse 2 dog eleph
  • Python 中的可逆 STFT 和 ISTFT

    有没有通用的形式短时傅立叶变换 https en wikipedia org wiki Short time Fourier transform与内置于 SciPy 或 NumPy 或其他什么中的相应逆变换 这是pyplotspecgram
  • 从 HDF5 文件中删除信息

    我意识到 SO 用户以前曾问过这个问题question https stackoverflow com questions 1124994 removing data from a hdf5 file rq 1但它是在 2009 年被问到的
  • Python 子进程:无法转义引号

    我知道以前曾问过类似的问题 但它们似乎都是通过重新设计参数的传递方式 即使用列表等 来解决的 但是 我这里有一个问题 因为我没有这个选项 有一个特定的命令行程序 我使用的是 Bash shell 我必须向其传递带引号的字符串 它不能不被引用

随机推荐