【发布时间】:2021-11-03 08:18:38
【问题描述】:
我正在创建一个文件列表中的行生成器,我的方法类似于:
def load(f_name: str):
with open(f_name, "r") as f:
lines = f.readlines()
# some calculations
return lines
def iter_files(f_names: list):
for f in f_names:
for line in load(f):
yield line
如果可能且有用的话,我想做的是加载下一个文件,同时屈服于另一个文件。 作为多处理的新手,我尝试了以下方法:
cache = dict()
def load(f_name: str, id: int):
global cache
with open(f_name, "r") as f:
lines = f.readlines()
# some calculations
cache[id] = lines
def iter_list(arr):
for x in arr:
yield x
def iter_files(f_names: list):
global cache
num_files = len(f_names)
load(f_names[0], 0)
for n in range(num_files - 1):
current = mp.Process(target=iter_list, args=(cache[n],))
next = mp.Process(target=load, args=(f_names[n + 1], n + 1))
current.start()
next.start()
current.join()
next.join()
del cache[n]
iter_list(cache[num_files - 1])
del cache[num_files - 1]
但除了看起来过于复杂之外,它还不起作用。
首先,如果我不将主代码放入 'if __name__ == "__main__":' 中(我不希望这是强制性的),我会收到以下错误:
RuntimeError:
An attempt has been made to start a new process before the
current process has finished its bootstrapping phase.
但是即使我这样做了文件也不会添加到缓存中:
current = mp.Process(target=iter_list, args=(cache[n],))
KeyError: 1
是否有可能实现我想要做的事情?我做错了什么?
谢谢大家
【问题讨论】:
-
“如果可能和有用的话,我想做什么”。可能,当然。有用?这取决于你用这些线做什么。如果处理量与 I/O 相比较小(可能很容易慢 100 倍),那么您不会看到额外的复杂性带来任何显着的加速。
-
@Thomas 文件非常小(平均 50kB),但它们的编码使得每个字节或多或少对应于已处理列表的条目,所以我猜加载算法的缓慢部分是“#一些计算”,而不是文件的实际变红。
标签: python multiprocessing yield