【问题标题】:python using w modepython使用w模式
【发布时间】:2017-04-21 13:26:17
【问题描述】:

在 linux 中,如果我有并行进程使用 w/w+ 模式写入同一个文件。 从两个进程写入的数据是否有可能混淆。或者它是否总是只包含一个进程在给定时间的数据,因为 w 模式会截断现有文件?

【问题讨论】:

  • 不完全是答案,但相关。 stackoverflow.com/questions/12942915/…
  • 您提供的链接,如果我理解正确的话,它会处理像我的示例中那样附加而不是覆盖的情况,
  • 这里的问题不一定是多个进程不能写入文件,因为它们可以。然而,问题是文件写入是在 python 或该系统上实现的。例如,fopen 有自己的内部 I/O 缓冲区,可能会覆盖其他缓冲区。在我的例子中,它显示最后一个要关闭的流在那里得到了它的内容,但是你可以通过使用 file.flush()file 来允许它们覆盖和写入整个文档(一次一个字母) 987654325@对象。
  • 我明白了。这就是为什么我在linux中专门询问python的原因。我假设在 python 中它应该以相同的方式实现它,而不管操作系统如何。正确的?如果是这样,我很好奇在这种情况下会发生什么
  • 如果重要的话,我在 Debian 8.1 上进行了测试。

标签: python linux file


【解决方案1】:

假设有进程 A 和进程 B 将写入同一个文件。 (w/w+ 模式不是 a/a+ 附加模式)

如果B在A编辑文件后写入文件,A的编辑将消失。

如果A在B编辑文件后写入文件,B的编辑将消失。

如果 B 在 A 编辑文件后打开文件,结果取决于您的程序。由于 A 的意外编辑或 A 的再次编辑可能会消失,因此可能会出现错误。但是,如果您没有在程序中模仿附加模式,则编辑不会堆叠。

反之亦然。

其实最后的作者会赢。

您必须意识到异步处理 w/w+ 模式不是一个好主意。但是这种“搞砸”的情况只能发生在追加模式而不是写入模式。

How do you append to a file?

【讨论】:

  • 这就是我想要确保的。我只想确保通过使用 w/w+ 我不会弄乱数据。我不在乎某些内容是否会被覆盖和删除
  • @user4906231 是的,很高兴看到您对我的回答感到满意。
  • @user4906231 不,在 Windows 上,二进制文件有所不同:docs.python.org/2/tutorial/…
  • 我明白了,但特别是对于 w/w+ 模式,它是一样的,对吧?
  • @user4906231 w :打开一个仅供写入的文件。如果文件存在,则覆盖文件。如果文件不存在,则创建一个新文件进行写入。 w+ :打开一个文件进行读写。如果文件存在,则覆盖现有文件。如果文件不存在,则创建一个新文件进行读写。 wb/wb+ :二进制相同。
【解决方案2】:

这完全取决于您打开文件的方式以及打开它的平台。

在 Linux/Mac 上,文件系统是 inode,文件 names 只是指向特定的 inode。所以如果你有一些像这样工作的代码:

import time
import threading

def write_one():
    f = open('test.txt', 'w')
    f.write('something longer ')
    time.sleep(0.5)
    f.write(' something more')

def write_two():
    f = open('test.txt', 'w')
    time.sleep(0.1)
    f.write('something shorter')

if __name__ == '__main__':
    t1 = threading.Thread(target=write_one)
    t2 = threading.Thread(target=write_two)

    t1.start()
    t2.start()

    t1.join()
    t2.join()
    print('Done')

将会发生的事情是一个线程打开文件进行写入,然后当下一个线程打开文件时,它将指向一个新的 inode 并更改文件名指向的位置。

如果你有这样的代码:

import time                                 
import threading                            

f = open('test.txt', 'w')                   

def write_one():                            
    f.write('something longer ')            
    time.sleep(0.5)                         
    f.write(' something more')              

def write_two():                            
    time.sleep(0.1)                         
    f.write('something shorter')            

if __name__ == '__main__':                  
    t1 = threading.Thread(target=write_one) 
    t2 = threading.Thread(target=write_two) 

    t1.start()                              
    t2.start()                              

    t1.join()                               
    t2.join()                               
    print('Done')   

两个线程都可以访问同一个文件对象。您可能可以通过复制做一些奇怪的事情,但我不会依赖它。

但是,如果您使用的是 Windows,则第一种方法可能行不通。 Windows 不喜欢一次打开多个进程的文件句柄。它会大声抱怨,可能会引发异常。

只是不要这样做。更好的方法是让 one 线程执行 IO,如果您想写入文件,让您的其他线程使用队列或其他东西将数据发送到您的 IO 线程。

【讨论】:

  • 在您的第一个示例中,数据将无法在两个线程之间混合?它们总是会互相覆盖,对吧?
  • 最后打开文件的线程将写入剩余的文件。
【解决方案3】:

在 Linux/Mac 上,……

将会发生的事情是一个线程打开文件进行写入,然后当下一个线程打开文件时,它将指向一个新的 inode 并更改文件名指向的位置。

这个陈述是错误的,上面的程序可以很容易地纠正以证明错误。 如果我们两者都改变​​

    f = open('test.txt', 'w')

    f = open('test.txt', 'w', 0)

我们不会被输出缓冲所欺骗(参见How often does python flush to a file?),并且能够得到输出

something shorter something more

test.txt 中,这清楚地表明两个open() 调用都打开了相同的inode

数据不能在两个线程之间混合?它们总是会互相覆盖,对吧?

正如我们所见,这是错误的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-18
    • 2023-01-31
    • 1970-01-01
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    相关资源
    最近更新 更多