Python 多进程操作文件,文件锁好像并没有生效

import multiprocessing
import json
import time
import fcntl


def init():
    with open('list.txt', 'w') as f:
        f.write(json.dumps({'sids': {}}))


def list(data=None):
    if data is None:
        with open('list.txt', 'r') as f:
            fcntl.lockf(f.fileno(), fcntl.LOCK_EX)
            print(f.read())
            return json.loads(f.read())
    else:
        with open('list.txt', 'w') as f:
            fcntl.lockf(f.fileno(), fcntl.LOCK_EX)
            f.write(json.dumps(data))


def generate(sid):
    target = 'http://www.baidu.com'
    data = list()
    data['sids'][sid] = target
    print(len(data['sids']))
    list(data)
    time.sleep(5)


if __name__ == '__main__':
    init()
    processes = []
    for i in range(100):
        p = multiprocessing.Process(target=generate, args=(i,))
        processes.append(p)
        p.start()

    for p in processes:
        p.join()

几乎所有进程都报 json 解码错误

    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded
阅读 8.8k
5 个回答

报这个错是因为你

return json.loads(f.read())

前面用了

print(f.read())

所以你json.loads的参数始终都是空字符串,所以一直报错。
另外,同意楼上说的不要随便用list这种关键字,到时候坑死自己。

给你一段参考的代码吧,你自己领会一下加锁哪里出问题了。

import multiprocessing
import json
import time
import fcntl


def init():
    with open('list.txt', 'w') as f:
        f.write(json.dumps({'sids': {}}))


def list_tmp(sid, target):
    with open('list.txt', 'r+') as f:
        fcntl.flock(f, fcntl.LOCK_EX)
        text = f.read()
        data = json.loads(text)
        data['sids'][sid] = target
        f.seek(0)
        f.truncate()
        f.write(json.dumps(data))


def generate(sid):
    target = 'http://www.baidu.com'
    list_tmp(sid, target)
    time.sleep(5)


if __name__ == '__main__':
    init()
    processes = []
    for i in range(100):
        p = multiprocessing.Process(target=generate, args=(i,))
        processes.append(p)
        p.start()

    for p in processes:
        p.join()

你是通过 fcntl.lockf(f.fileno(), fcntl.LOCK_EX) 来进行加锁的, 没加加锁的都是新open的文件, 每个文件的fileno()当然不一样啊, 即使它们open是同一个文件. 之所以报 No JSON object could be decoded 是因为读了一个正在写的文件, 读取不全所以导致转换json异常.

是不是f.read()的内容格式不对, 是不是需要添加encoding=?参数

在操作文件之前先创建一个锁,锁用完之后需要删除,另外建议你最好不要用关键字来命名,不然以后你踩了坑可能找了半天还没定位到问题在哪

def list(data=None):
    if data is None:
        with open('list.txt', 'r') as f:
            fcntl.flock(f, fcntl.LOCK_EX)
            data = json.loads(f.read())
            fcntl.flock(f, fcntl.LOCK_UN)
            return data
    else:
        with open('list.txt', 'w') as f:
            fcntl.flock(f, fcntl.LOCK_EX)
            f.write(json.dumps(data))
            fcntl.flock(f, fcntl.LOCK_UN)
新手上路,请多包涵

这个错是你读的内容不是json格式,读的模式二进制

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题