我正在寻找一种允许并发文件对象搜索的方法。
作为文件寻求警惕的测试案例:
#!/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。在我的实际情况中,更难做到这一点。)
答案 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)
与任何锁定一样,您希望在保持时尽可能少地执行逻辑。它不允许同时寻求,但它会阻止一个过程中的寻求干扰其他过程中的寻求。
当然,最好在每个进程中打开文件,以便每个进程都有自己的文件位置概念 - 但是你已经说过你不能。重新思考; - )