为什么不是';我的文件在Python中从多个进程写入时是否已损坏?

为什么不是';我的文件在Python中从多个进程写入时是否已损坏?,python,linux,file,multiprocessing,python-multiprocessing,Python,Linux,File,Multiprocessing,Python Multiprocessing,显然,如果write()调用没有以某种方式同步,那么从多个进程写入同一文件可能会导致数据损坏。请参阅其他问题: 然而,为了测试的目的,我试图复制这个可能的错误,我无法导致文件消息混淆。我想这样做是为了有效地比较有锁和没有锁的安全性 在不做任何事情的情况下,文件似乎受到了某种程度的保护 import multiprocessing import random NUM_WORKERS = 10 LINE_SIZE = 10000 NUM_LINES = 10000 def writer(i):

显然,如果
write()
调用没有以某种方式同步,那么从多个进程写入同一文件可能会导致数据损坏。请参阅其他问题:

然而,为了测试的目的,我试图复制这个可能的错误,我无法导致文件消息混淆。我想这样做是为了有效地比较有锁和没有锁的安全性

在不做任何事情的情况下,文件似乎受到了某种程度的保护

import multiprocessing
import random

NUM_WORKERS = 10
LINE_SIZE = 10000
NUM_LINES = 10000

def writer(i):
    line = ("%d " % i) * LINE_SIZE + "\n"
    with open("file.txt", "a") as file:
        for _ in range(NUM_LINES):
            file.write(line)

def check(file):
    for _ in range(NUM_LINES * NUM_WORKERS):
        values = next(file).strip().split()
        assert len(values) == LINE_SIZE
        assert len(set(values)) == 1

if __name__ == "__main__":
    processes = []

    for i in range(NUM_WORKERS):
        process = multiprocessing.Process(target=writer, args=(i, ))
        processes.append(process)

    for process in processes:
        process.start()

    for process in processes:
        process.join()

    with open("file.txt", "r") as file:
        check(file)
我正在使用Linux,而且我也知道文件写入可能是原子的,具体取决于缓冲区大小:

我试图增加消息的大小,但它不会产生损坏的数据


您知道我可以使用哪些代码示例在Linux上使用多处理生成损坏的文件吗?

AFAIU,锁定是由内核完成的。即使您没有要求锁定,您也会看到锁定效果的原因是
O_NONBLOCK
file status标志在默认情况下是未设置的(我想在打开文件时)

请参阅手册中有关文件状态标志的部分,特别是请参阅和
man 2 fcntl

我对您的示例进行了修补,以查看
O_NONBLOCK
的效果(事实上,断言现在确实失败了):


信用:参见例如和(和/或
man 3p write
)。

当我一个字符一个字符地写文件时,我设法损坏了文件,而不是按行:
对于第行:file中的c。write(c)
@AndrejKesely在这种情况下,我想这是意料之中的,因为有多个
write
操作。我以为对
file.write()
的一次调用都不安全。
--- 1.py.orig   2019-07-05 14:49:13.276289018 +0300
+++ 1.py        2019-07-05 14:51:11.674727731 +0300
@@ -1,5 +1,7 @@
 import multiprocessing
 import random
+import os
+import fcntl

 NUM_WORKERS = 10
 LINE_SIZE = 10000
@@ -8,6 +10,8 @@
 def writer(i):
     line = ("%d " % i) * LINE_SIZE + "\n"
     with open("file.txt", "a") as file:
+        flag = fcntl.fcntl(file.fileno(), fcntl.F_GETFD)
+        fcntl.fcntl(file.fileno(), fcntl.F_SETFL, flag | os.O_NONBLOCK)
         for _ in range(NUM_LINES):
             file.write(line)