Python多线程与文件锁定问题

0 投票
1 回答
1015 浏览
提问于 2025-04-18 11:19

我用两种方法实现了多线程代码,但在这两种方法中都遇到了错误。有人能解释一下问题出在哪里吗?

在第一种方法中,我收到了一个异常,提示说传给writekey函数的参数有两个,而不是一个。
在第二种方法中,其中一个线程读取了空行,因此在处理这个空字符串时出现了异常。

我使用了锁,这不是应该防止多个线程同时访问这个函数或文件吗?

第一种方法:

class SomeThread(threading.Thread):
    def __init__(self, somequeue, lockfile):
        threading.Thread.__init__(self)
        self.myqueue = somequeue
        self.myfilelock = lockfile

    def writekey(key):
        if os.path.exists(os.path.join('.', outfile)):
            with open(outfile, 'r') as fc:
                readkey = int(fc.readline().rstrip())
            os.remove(os.path.join('.', outfile))

        with open(outfile, 'w') as fw:
            if readkey > key:
                fw.write(str(readkey))
            else:
                fw.write(str(key))

    def run(self):
        while(True):
            dict = self.myqueue.get()

            self.myfilelock.acquire()
            try:
                self.writekey(dict.get("key"))
            finally:
                self.myfilelock.release()

            self.myqueue.task_done()

populateQueue() # populate queue with objects    
filelock = threading.Lock()

for i in range(threadnum):
    thread = SomeThread(somequeue, filelock)
    thread.setDaemon(True)
    thread.start()

somequeue.join()

第二种方法:

def writekey(key):
    if os.path.exists(os.path.join('.', outfile)):
        with open(outfile, 'r') as fc:
            # do something...

        os.remove(os.path.join('.', outfile))

    with open(outfile, 'w') as fw:
        # do something...

class SomeThread(threading.Thread):
    def __init__(self, somequeue, lockfile):
        threading.Thread.__init__(self)
        self.myqueue = somequeue
        self.myfilelock = lockfile

    def run(self):
        while(True):
            dict = self.myqueue.get()

            self.myfilelock.acquire()
            try:
                writekey(dict.get("key"))
            finally:
                myfilelock.release()

            self.myqueue.task_done()

# Same as above ....

1 个回答

0

在版本1中,def writekey(key) 这个函数的第一个参数应该加上 "self",也就是这样写:

def writekey(self, key):

版本2中的问题就不太明显了。我猜是在读取outfile的时候,遇到了一个空行。这是正常现象,意味着文件的末尾已经到了。通常情况下,你会在读取循环中直接跳出。一般来说,逐行读取文件会更好,可以用一个for循环来实现,比如:

with open(outfile, 'r') as fc:
    for line in fc:
        # process the line

当到达文件末尾时,for循环会自然结束。

撰写回答