【问题标题】:Python: concurrent file seekPython:并发文件搜索
【发布时间】:2016-10-06 14:41:24
【问题描述】:

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

作为文件搜索谨慎的测试用例:

#!/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。在我的实际情况下,这样做更难。)

【问题讨论】:

    标签: python concurrency


    【解决方案1】:

    你不能 - Python I/O 建立在 C 的 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)
    

    与任何锁一样,您希望在持有它的同时尽可能少地执行逻辑上的必要操作。它不允许并发查找,但会防止一个进程中的查找干扰其他进程中的查找。

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

    【讨论】:

    • 啊 - 我从 C dup() manual 看到...“它们引用相同的打开文件描述,因此共享文件偏移量和文件状态标志”
    • 好吧,我记得在大学时在构建 shell 时使用了dup2(),我想我也使用过dup()。它似乎主要用作一种引用计数系统,以避免关闭实际的文件通道。
    猜你喜欢
    • 2016-09-22
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 2011-08-30
    • 2010-10-06
    • 2012-11-19
    • 1970-01-01
    相关资源
    最近更新 更多