Python:并发文件搜索

时间:2016-06-06 20:56:48

标签: python concurrency

我正在寻找一种允许并发文件对象搜索的方法。

作为文件寻求警惕的测试案例:

#!/usr/bin/env python2
import time, random, os
s = 'The quick brown fox jumps over the lazy dog'

# create some file, just for testing
f = open('file.txt', 'w')
f.write(s)
f.close()

# the actual code...
f = open('file.txt', 'rb')
def fn():
    out = ''
    for i in xrange(10):
        k = random.randint(0, len(s)-1)
        f.seek(k)
        time.sleep(random.randint(1, 4)/10.)
        out += s[k] + ' ' + f.read(1) + '\n'
    return out

import multiprocessing
p = multiprocessing.Pool()
n = 3
res = [p.apply_async(fn) for _ in xrange(n)]
for r in res:
    print r.get()
f.close()

我有工作流程,在文件中随机搜索,然后是sleep,然后是read。我将它们read与实际字符串字符进行比较。我不会立即打印以避免打印时出现并发问题。

你可以看到n=1时,一切顺利,但由于文件描述符中的并发性,n>1时所有内容都会误入歧途。

我试图在fn()中复制文件描述符:

def fn():
    fd = os.dup(f)
    f2 = os.fdopen(fd)

然后我使用f2。但它似乎没有帮助。

如何同时进行搜索,即从多个进程中进行搜索? (在这种情况下,我只能open fn()内的文件,但这是一个MWE。在我的实际情况中,更难做到这一点。)

1 个答案:

答案 0 :(得分:0)

你不能 - 在C的I / O上构建Python I / O,并且在C中每个打开的文件只有一个“当前文件位置”。这本身就是共享的。

您可以做的是在进程间锁定的保护下执行搜索+读取。

喜欢定义:

def process_init(lock):
    global seek_lock
    seek_lock = lock

并在主进程中将其添加到Pool构造函数:

initializer=process_init, initargs=(multiprocessing.Lock(),)

然后,无论何时你想要寻求和阅读,都要在该锁的保护下进行:

with seek_lock:
     f.seek(k)
     char = f.read(1)

与任何锁定一样,您希望在保持时尽可能少地执行逻辑。它不允许同时寻求,但它会阻止一个过程中的寻求干扰其他过程中的寻求。

当然,最好在每个进程中打开文件,以便每个进程都有自己的文件位置概念 - 但是你已经说过你不能。重新思考; - )