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

2017-08-24 12:46:20 +08:00
 40huo
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

这是哪里出了问题?

6143 次点击
所在节点    Python
15 条回复
wayslog
2017-08-24 13:37:30 +08:00
data['sids'][sid] = target
print(len(data['sids']))

sid from ????
xfwduke
2017-08-24 13:50:09 +08:00
试试 list 函数直接把 f 返回出去, 并且让外部一直持有这个对象
之前碰到过类似的问题. 写了个

def lock (filename) 这样的函数
一直不生效

应该是在函数内部打开文件, 文件对象在函数完成后就关闭了. 锁也释放了
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
```
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

直接报错了,真的能这么写吗
wwqgtxx
2017-08-24 14:01:28 +08:00
我怎么觉得问题在这里
print(f.read())
return json.loads(f.read())
你读了两遍,写的时候却只写了一遍
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
40huo
2017-08-24 14:06:18 +08:00
@wwqgtxx #5 是有这个问题,去掉 print 后有少部分进程报 raise ValueError("No JSON object could be decoded")错误
40huo
2017-08-24 14:07:34 +08:00
@a87150 #4 list 是我自定义的函数,不是定义了一个列表。。。命名问题是我的锅。。。函数返回的是一个字典。
40huo
2017-08-24 14:08:58 +08:00
@zhangysh1995 #6 试过了,一样的问题
zhangysh1995
2017-08-24 14:11:17 +08:00
@wwqgtxx 刚才试了一下,这句话确实有问题,第二遍的时候 buffer 应该是空了
40huo
2017-08-24 14:24:41 +08:00
@zhangysh1995 #10 本来应该写 100 个,现在每次都有那么 4,5 个写失败。。。感觉这文件锁和假的一样。。。
topbandit
2017-08-24 14:56:35 +08:00
file lock 在打开文件之前获取,你把 fcntl.lockf(f.fileno(), fcntl.LOCK_EX)提到 open file 前面
wwqgtxx
2017-08-24 15:03:12 +08:00
@topbandit 你在 open 之前根本就没有 f 这个对象,怎么 lock
lolizeppelin
2017-08-24 17:22:07 +08:00
直接 fork 不要用库试试
virusdefender
2017-08-24 17:25:23 +08:00
6 楼正解

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/385420

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX