在python中写入文件时的并发性

在python中写入文件时的并发性,python,python-3.x,sockets,io,Python,Python 3.x,Sockets,Io,我现在正在用python3开发一个p2p文件共享系统,我遇到了一个问题,我不知道如何准确地解决 我有一个服务器进程和一个客户机进程的对等点,其中一个客户机进程连接到其他节点,将其放在自己的线程中,并通过套接字侦听数据。当仅从另一个对等方下载时,文件写入正确,没有问题,但当文件在多个对等方上拆分时,文件已损坏。数据正确地从其他两个对等方接收,因此我认为这将是一个文件写入问题 当我从对等方获取数据时,我打开文件,寻找数据来源的位置,然后写入并关闭文件。锁是解决这个问题的方法吗 这是它自己的线程中不断

我现在正在用python3开发一个p2p文件共享系统,我遇到了一个问题,我不知道如何准确地解决

我有一个服务器进程和一个客户机进程的对等点,其中一个客户机进程连接到其他节点,将其放在自己的线程中,并通过套接字侦听数据。当仅从另一个对等方下载时,文件写入正确,没有问题,但当文件在多个对等方上拆分时,文件已损坏。数据正确地从其他两个对等方接收,因此我认为这将是一个文件写入问题

当我从对等方获取数据时,我打开文件,寻找数据来源的位置,然后写入并关闭文件。锁是解决这个问题的方法吗

这是它自己的线程中不断侦听的代码

def handleResponse(clientConnection, fileName, fileSize):
    # Listen for connections forever
    try:
        while True:
            #fileName = ""
            startPos = 0
            data = clientConnection.recv(2154)
            # If a response, process it
            if (len(data) > 0):
                split = data.split(b"\r\n\r\n")
                #print(split[0])
                headers = split[0].replace(b'\r\n', b' ').split(b' ')
                # Go through the split headers and grab the startPos and fileName
                for i in range(len(headers)):
                    if (headers[i] == b"Range:"):
                        startPos = int(headers[i+1])
                        #fileName = headers[i+2].decode()
                        break
                # Write the file at the seek pos
                mode = "ab+"
                if (startPos == 0):
                    mode = "wb+"
                with open ("Download/" + fileName, mode) as f:
                    f.seek(startPos, 0)
                    f.write(split[1])
                    f.close()

斯蒂芬·乌尔里希回答


解决方案是用rb+而不是ab+打开文件,查找位置并写入。请注意,如果文件不存在,它将抛出异常,因为它不是在rb+

中创建的,为什么要以追加模式打开文件?发件人:…'在某些Unix系统上,表示所有写入都会附加到文件的末尾,而不管当前搜索位置如何……我在MacOS上不知道这一点。在多个线程无序写入数据的情况下,这就是损坏我的文件的原因吗?如果是这样的话,这是有道理的。实际上,我看不出有任何理由首先使用append打开文件,无论是否使用并发访问。你应该打开文件进行写入,而不是附加,你只需要寻找你想要的位置,不管位置是什么。是的,因为w会覆盖文件(如果存在),所以我必须读取文件的初始内容,将数据插入正确的位置,然后写入整个块。如果我走错了方向,请纠正我,但我认为我走对了方向。谢谢实际上,r+可以做我需要的事情,我只需要在写入之前创建文件,否则它会失败。谢谢你的帮助!