
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 这是哪里出了问题?
放一个目前没问题的。
import multiprocessing import json import time import fcntl def init(): with oen('list.txt', 'w') as f: f.write(json.dumps({'sids': {}})) def list_tmp(data=None): if data is None: with open('list.txt', 'r') as f: fcntl.flock(f, fcntl.LOCK_EX) data = f.read() return json.loads(data) else: with open('list.txt', 'r+') as f: fcntl.flock(f, fcntl.LOCK_EX) text = f.read() text = json.loads(text) text['sids'][data[0]] = data[1] f.seek(0) f.truncate() f.write(json.dumps(text)) def generate(sid): target = 'http://www.baidu.com' data = (sid, target) list_tmp(data) time.sleep(1) 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() with open('list.txt', 'r') as f: data = f.read() data = json.loads(data) print(len(data.get('sids'))) 之前的代码读入旧数据不应该在写的部分的外面,这样多进程读入的本来就是不全的数据,另外 seek 和 truncate 也有很明显的作用,原因不知。。。
1 wayslog 2017-08-24 13:37:30 +08:00 data['sids'][sid] = target print(len(data['sids'])) sid from ???? |
2 xfwduke 2017-08-24 13:50:09 +08:00 试试 list 函数直接把 f 返回出去, 并且让外部一直持有这个对象 之前碰到过类似的问题. 写了个 def lock (filename) 这样的函数 一直不生效 应该是在函数内部打开文件, 文件对象在函数完成后就关闭了. 锁也释放了 |
3 xfwduke 2017-08-24 13:54:22 +08:00 ```python def set_lock(block=False): lock_f = open(os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), '.{0}.lock'.format(os.path.splitext(os.path.basename(sys.argv[0]))[0])), 'w') if block: fcntl.flock(lock_f.fileno(), fcntl.LOCK_EX) else: fcntl.flock(lock_f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) return lock_f ``` |
4 a87150 2017-08-24 14:00:24 +08:00 Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> data = list() >>> target = 'http://www.baidu.com' >>> data['sids'][0] = target Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: list indices must be integers or slices, not str 直接报错了,真的能这么写吗 |
5 wwqgtxx 2017-08-24 14:01:28 +08:00 我怎么觉得问题在这里 print(f.read()) return json.loads(f.read()) 你读了两遍,写的时候却只写了一遍 |
6 zhangysh1995 2017-08-24 14:05:29 +08:00 lockf -> flock 试试,参考 https://stackoverflow.com/questions/28470246/python-lockf-and-flock-behaviour 你的 lock 用错了。lockf 对每一个人进程的 file descriptor 都是独立的,所以没用。 官方文档: https://docs.python.org/3/library/fcntl.html |
7 40huo OP @wwqgtxx #5 是有这个问题,去掉 print 后有少部分进程报 raise ValueError("No JSON object could be decoded")错误 |
9 40huo OP @zhangysh1995 #6 试过了,一样的问题 |
10 zhangysh1995 2017-08-24 14:11:17 +08:00 @wwqgtxx 刚才试了一下,这句话确实有问题,第二遍的时候 buffer 应该是空了 |
11 40huo OP @zhangysh1995 #10 本来应该写 100 个,现在每次都有那么 4,5 个写失败。。。感觉这文件锁和假的一样。。。 |
12 topbandit 2017-08-24 14:56:35 +08:00 file lock 在打开文件之前获取,你把 fcntl.lockf(f.fileno(), fcntl.LOCK_EX)提到 open file 前面 |
14 lolizeppelin 2017-08-24 17:22:07 +08:00 via Android 直接 fork 不要用库试试 |
15 virusdefender 2017-08-24 17:25:23 +08:00 via iPhone 6 楼正解 |