2

我将有一个子进程发送LDAP查询和其他子进程来检索响应。 在两个进程之间共享LDAP对象时出现问题。有人能指点我一个解决方案吗?Python多处理无法将LDAP对象共享到子进程

import ldap 
from multiprocessing import Process 


def send_ldap(ldap_conn): 
    print ldap_conn 

def receive_ldap(ldap_conn): 
    print ldap_conn 

def main(): 
    ldap_conn = ldap.initialize('ldap://abc:12345') 
    ldap_sender = Process(target=send_ldap, args=(ldap_conn,)) 
    ldap_receiver = Process(target=receive_ldap, args=(ldap_conn,)) 
    ldap_sender.start() 


if __name__ == '__main__': 
    main() 

的错误是用腌汁模块:

Traceback (most recent call last): 
    File "t.py", line 22, in <module> 
    main() 
    File "t.py", line 16, in main 
    ldap_sender.start() 
    File "c:\python27\lib\multiprocessing\process.py", line 130, in start 
    self._popen = Popen(self) 
    File "c:\python27\lib\multiprocessing\forking.py", line 277, in __init__ 
    dump(process_obj, to_child, HIGHEST_PROTOCOL) 
    File "c:\python27\lib\multiprocessing\forking.py", line 199, in dump 
    ForkingPickler(file, protocol).dump(obj) 
    File "c:\python27\lib\pickle.py", line 224, in dump 
    self.save(obj) 
    File "c:\python27\lib\pickle.py", line 331, in save 
    self.save_reduce(obj=obj, *rv) 
    File "c:\python27\lib\pickle.py", line 419, in save_reduce 
    save(state) 
    File "c:\python27\lib\pickle.py", line 286, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "c:\python27\lib\pickle.py", line 649, in save_dict 
    self._batch_setitems(obj.iteritems()) 
    File "c:\python27\lib\pickle.py", line 681, in _batch_setitems 
    save(v) 
    File "c:\python27\lib\pickle.py", line 286, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "c:\python27\lib\pickle.py", line 548, in save_tuple 
    save(element) 
    File "c:\python27\lib\pickle.py", line 286, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "c:\python27\lib\pickle.py", line 725, in save_inst 
    save(stuff) 
    File "c:\python27\lib\pickle.py", line 286, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "c:\python27\lib\pickle.py", line 649, in save_dict 
    self._batch_setitems(obj.iteritems()) 
    File "c:\python27\lib\pickle.py", line 681, in _batch_setitems 
    save(v) 
    File "c:\python27\lib\pickle.py", line 286, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "c:\python27\lib\pickle.py", line 725, in save_inst 
    save(stuff) 
    File "c:\python27\lib\pickle.py", line 286, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "c:\python27\lib\pickle.py", line 649, in save_dict 
    self._batch_setitems(obj.iteritems()) 
    File "c:\python27\lib\pickle.py", line 681, in _batch_setitems 
    save(v) 
    File "c:\python27\lib\pickle.py", line 331, in save 
    self.save_reduce(obj=obj, *rv) 
Traceback (most recent call last): 
    File "c:\python27\lib\pickle.py", line 396, in save_reduce 
    File "<string>", line 1, in <module> 
     File "c:\python27\lib\multiprocessing\forking.py", line 381, in main 
save(cls) 
     File "c:\python27\lib\pickle.py", line 286, in save 
self = load(from_parent) 
     File "c:\python27\lib\pickle.py", line 1378, in load 
f(self, obj) # Call unbound method with explicit self 
    File "c:\python27\lib\pickle.py", line 748, in save_global 
    return Unpickler(file).load() 
    File "c:\python27\lib\pickle.py", line 858, in load 
    (obj, module, name)) 
pickle.PicklingError: Can't pickle <type 'thread.lock'>: it's not found as thread.lock 
dispatch[key](self) 
    File "c:\python27\lib\pickle.py", line 880, in load_eof 
    raise EOFError 
EOFError 

回答

2

的问题是,所述ldap_conn对象不是picklable,这是需要在Windows进程之间发送。这是不可挑选的,因为它在内部使用了一些不可挑选的threading.Lock对象。图书馆实际上声称提供了一个ReconnectLDAPObject,它应该是可以挑选的,但它已经坏掉了,而且也是不可挑选的。我们可以解决这个问题,虽然,由子类它和固定的bug(它错过去除之前酸洗内部锁中的一个):

from ldap.ldapobject import ReconnectLDAPObject 
from multiprocessing import Process 
import ldap 

class PicklableLDAPObject(ReconnectLDAPObject): 
    def __getstate__(self): 
     d = ReconnectLDAPObject.__getstate__(self) 
     del d['_reconnect_lock'] 
     return d 

    def __setstate__(self, d): 
     self._reconnect_lock = ldap.LDAPLock(desc='reconnect lock within %s' % (repr(self))) 
     ReconnectLDAPObject.__setstate__(self, d) 

def send_ldap(ldap_conn): 
    print ldap_conn 

def receive_ldap(ldap_conn): 
    print ldap_conn 

def main(): 
    #ldap_conn = ldap.initialize('ldap://abc:12345') 
    ldap_conn = PicklableLDAPObject('ldap://abc:12345') 
    ldap_sender = Process(target=send_ldap, args=(ldap_conn,)) 
    ldap_receiver = Process(target=receive_ldap, args=(ldap_conn,)) 
    ldap_sender.start() 

现在该对象将酸洗细,这意味着它应该multiprocessing是可用目的。

+0

我也[提交了一个错误](https://sourceforge.net/p/python-ldap/bugs/64/)的问题与'ReconnectLDAPObject'不可挑选。 – dano 2014-09-26 14:47:48

+0

我遇到了这个问题,除了我定义的自定义类而不是LDAP对象。我的类包含一些需要由子进程访问的不同数据对象,包括一个multiprocessing.lock,这是两个线程操作的一部分。有我的解决方案吗?我可以将句柄传递给需要访问的每个单独对象吗? (我不明白为什么/如何在这里使用腌菜,我也不熟悉LDAP) – kjgregory 2016-06-25 06:06:54