繁体   English   中英

Python 多处理 - 我们可以将 (itertools.islice) 可迭代对象直接传递给 pool.imap 而无需转换为列表吗?

[英]Python Multiprocessing - Can we pass an (itertools.islice) iterable directly to pool.imap whithout converting to a list?

在从 DB2(有些表有 1 亿)中读取大表后,我使用 itertools.islice 将生成器 object 转换为迭代器。 我将迭代器传递给 multiprocessing pool.map,它调用 function 将这些块并行提取到 CSV。

它有效,但在并行运行开始之前,python pool.map 将 ITERATOR 转换为消耗大量时间的 LIST。 有什么方法可以避免创建此列表或更快地转换为列表? 我也尝试使用 POOL.IMAP,但我的笔记本 kernel 在我运行该程序时死机了。 要使用 IMAP,我必须将迭代器转换为列表,这又需要时间。 有什么想法吗?

generator_df = pd.read_sql(query2, test_connection_forbankcv_connection, chunksize = 5000)
iterable_slice = list(it.islice(generator_df, slice_start,slice_end))
results = p.imap(chunk_to_csv, iterable_slice, 1) 

我马上承认,这个解决方案有一些问题,但它展示了基本思想:

import itertools
from typing import Iterable
from multiprocessing import Pool

class Lengthed_ISlice:
    def __init__(self, iterable: Iterable, start: int, stop: int):
        self._start = start
        self._stop = stop
        self._islice = itertools.islice(iterable, self._start, self._stop)

    def __len__(self):
        return self._stop - self._start

    def __iter__(self):
        return iter(self._islice)

这是islice object 上的一个薄包装器,它实现了所需的__len__方法,因此它可以与Poolmap方法一起使用:

def double(n):
    return n * 2

my_list = list(range(10, 100))

with Pool() as p:
    print(p.map(double, Lengthed_ISlice(my_list, 2, 9)))
    # Prints [24, 26, 28, 30, 32, 34, 36]

主要问题:

  • 除了__iter__之外,它没有正确地将任何功能委托给底层islice 如果您在/如果您扩展对此的使用时遇到有关缺少方法的错误,则需要实施正确的方法。
  • 为简洁起见,我没有考虑步骤,因为您没有使用非默认步骤,并且它们使数学稍微复杂了一点。
  • 我不担心使用Iterable的通用参数。 如果你想要更好的类型提示,你应该为构造函数参数和__iter__引入一个TypeVar

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM