【问题标题】:Multiprocessing pool apply_async function when applied to an Object throws Cannot pickle <type 'thread.lock'> objects应用于对象时的多处理池 apply_async 函数会抛出无法腌制 <type 'thread.lock'> 对象
【发布时间】:2015-04-02 19:27:56
【问题描述】:

我的__init__ 函数尝试调用调度程序类的函数verify_func()

def__init__:
def _pickle_method(method):
    func_name = method.im_func.__name__
    obj = method.im_self
    cls = method.im_class
    return _unpickle_method, (func_name, obj, cls)

def _unpickle_method(func_name, obj, cls):
    for cls in cls.mro():
        try:
            func = cls.__dict__[func_name]
        except KeyError:
            pass
    return func.__get__(obj, cls)


if __name__=='__main__':
  while True:
    #Create a scheduler object
    scheduler_obj=Scheduler()
    try:
      #Connect to the database get all the new requests to be verified
      db = Database(scheduler_obj.username_testschema, scheduler_obj.password_testschema, scheduler_obj.mother_host_testschema,
                    scheduler_obj.mother_port_testschema, scheduler_obj.mother_sid_testschema, 0)
      result = db.query("SELECT JOB_ID FROM %s.table_1 WHERE JOB_STATUS='%s'" % (scheduler_obj.username_testschema, 'initiated'))
      copy_reg.pickle(types.MethodType, _pickle_method, _unpickle_method)
      pool = mp.Pool(len(result))
      for row in result:
        verify_id = row[0]
        print mp.current_process()
        try:
          pool.apply_async(scheduler_obj.verify_func, (verify_id))
        except Exception as e:
                    scheduler_obj.logger.exception("MP exception : %s", e)

      pool.close()
      pool.join()

    except Exception as e:
      scheduler_obj.logger.exception(e)
    finally:
      time.sleep(10)

这个verify_func 尝试使用 cx_oracle 对数据库运行一些查询。

def verify_func(self,verify_id):
    print "Verifying with Current Id : ", verify_id
    try:
      db = Database(self.username_testschema, self.password_testschema, self.mother_host_testschema,
                    self.mother_port_testschema, self.mother_sid_testschema, 0)
      result = db.query("select * from %s.table_2 where job_id=%d" % (self.username_testschema,verify_id))
      column_name = [d[0] for d in db.cursor.description]
      final_dictionary = [dict(zip(column_name, row)) for row in result]

      #On getting the new job_ids whose status is .. try to run checks for each one.
      for row in final_dictionary:
        print row

它是否连接并在数据库上运行查询,这会引发此错误,因为它没有说明它到底在哪里中断。

class Database(object):
 def __init__:
    self.connection = cx_Oracle.connect(self.connect_string, mode=self.mode) 

如果需要更多解释,请告诉我。

【问题讨论】:

  • Scheduler 实例内部有一个对象,其中包含一个无法腌制的 threading.Lock。您可能需要将 __getstate__/__setstate__ 方法添加到 Scheduler 类中,以便在酸洗之前从实例中删除有问题的对象。
  • 好的,但是哪个对象,无法追踪?让我试试。谢谢@dano。
  • 我通常会通过挖掘源代码来弄清楚。您可能可以在 pickle 模块中添加一些跟踪,以帮助准确识别哪个对象,但我无法告诉您将其添加到哪个函数。
  • 是的,我做了一个 scheduler_object.__dict__ ,我看到我有一个记录器实例变量,它是不可腌制的。谢谢达诺。

标签: python pickle cx-oracle python-multiprocessing


【解决方案1】:

是的,我做了一个 scheduler_object.dict,我看到我有一个记录器实例变量,它是不可腌制的。谢谢@Dano。

因此,最好的调试方法是找出类变量/方法可能是什么,因为如果您遇到此错误。 此外,您可以覆盖记录器类的 getstatesetstate 方法以使其可腌制,如此处所示。 Can't pickle loggers?

【讨论】:

  • 尝试将import dill 添加到代码顶部。 dill 知道如何在没有 _unpickle_method 业务的情况下腌制实例方法和锁以及各种其他东西。如果这不起作用,b/c 你正在使用multiprocessing,你可以改用pathos.multiprocessing,它是multiprocessing 的分支,它用pickle 代替了pickle 的使用。
  • 好心的先生,我会试试看的。
猜你喜欢
  • 1970-01-01
  • 2017-04-02
  • 2014-04-27
  • 1970-01-01
  • 2021-06-17
  • 2019-02-19
  • 2019-03-03
  • 2020-09-22
  • 2022-01-02
相关资源
最近更新 更多