Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python类型错误:can';将生成器与多处理结合使用时,pickle生成器对象_Python_Multiprocessing_Generator - Fatal编程技术网

python类型错误:can';将生成器与多处理结合使用时,pickle生成器对象

python类型错误:can';将生成器与多处理结合使用时,pickle生成器对象,python,multiprocessing,generator,Python,Multiprocessing,Generator,我有一个函数,叫做fun(),它生成生成器。我想检查生成器是否为空,因为我想节省尽可能多的运行时间,所以我 不要将其转换为列表并检查其是否为空。 相反,我这样做: def peek(iterable): try: first = next(iterable) except StopIteration: return None return first, itertools.chain([first], iterable) 我使用的多处理方

我有一个函数,叫做
fun()
,它
生成
生成器。我想检查生成器是否为空,因为我想节省尽可能多的运行时间,所以我
不要将其转换为列表并检查其是否为空。
相反,我这样做:

def peek(iterable):
    try:
        first = next(iterable)
    except StopIteration:
        return None
    return first, itertools.chain([first], iterable)
我使用的多处理方式如下:

def call_generator_obj(ret_val):
    next = peek(ret_val)
    if next is not None:
        return False
    else:
        return True


def main():
    import multiprocessing as mp
    pool = mp.Pool(processes=mp.cpu_count()-1)
    # for loop over here
        ret_val = fun(args, kwargs)
        results.append(pool.apply(call_generator_obj, args=(ret_val,))
        # the above line throws me the error
据我所知,pickle是在将内存中的某个对象转换为字节流时进行的,我在我的任何函数中都是这样做的

回溯:(在尖线之后)

据我所知,酸洗是在将内存中的某个对象转换为字节流时进行的,我不认为我在这里做过类似的事情

好吧,你正在这么做

不能在进程之间直接传递Python值。即使是最简单的变量也会在进程内存空间中的某个位置保存指向某个结构的指针,而仅仅将该指针复制到另一个进程会给您一个segfault或垃圾,这取决于另一个进程中的同一内存空间是未映射还是映射到完全不同的内容。像发电机这样复杂的东西,基本上是一个活跃的堆栈框架,将是更不可能的

多处理
解决这一问题的方法是透明地pickle您赋予它的所有内容。函数及其参数和返回值都需要进行pickle处理


如果你想知道它是如何工作的:一个
池基本上是通过一个
队列
工作的,父
s任务放在任务基本上是
(func,args)
对的位置,子
任务取下。而
队列
基本上是通过调用
pickle.dumps(value)
然后将结果写入管道或其他进程间通信机制来工作的。

hmmm。。。那么有什么解决方案/解决办法吗?不必将生成器转换为列表?这是节省运行时间的问题,我正在处理非常大的数据☹️@能源部没有完全通用的解决方案。对于大多数应用程序,都有特定的解决方案,您可以重写迭代,这样就可以在父应用程序中获取一个或多个值并将其传递给池函数,而不是传递迭代器。但是对于这里发布的代码,唯一可见的工作是在生成器上调用
next
。如果您的真实代码也是如此,那么可能需要进行更大的更改。您所说的“唯一可见的工作是调用生成器上的next”是什么意思?你是说这就是造成问题的原因,对吗?是的,这是我代码的顶级摘要。我想我必须运行一个分析器,在生成器或multiprocessing@J.Doe好的,是的,但问题是,在生成器函数中可能有真正的功在做,如果你能展示出真正的功,例如,
可能会产生一系列可以传递给函数的值,不必产生调用该函数的结果,您就可以进行多进程处理,而无需从头重写所有内容。(当然,这几乎肯定意味着打破一个使代码可读/可维护/通用的抽象,但有时为了性能着想,你不得不这么做。)对不起,伙计,它是开源的,如果我尝试这么做,人们会发疯的
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/pool.py", line 253, in apply
    return self.apply_async(func, args, kwds).get()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/pool.py", line 608, in get
    raise self._value
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/pool.py", line 385, in _handle_tasks
    put(task)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/connection.py", line 206, in send
    self._send_bytes(_ForkingPickler.dumps(obj))
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/reduction.py", line 51, in dumps
    cls(buf, protocol).dump(obj)
TypeError: can't pickle generator objects