Hang in Python script using SQLAlchemy and multiprocessing

后端 未结 4 1831
北海茫月
北海茫月 2021-01-05 06:48

Consider the following Python script, which uses SQLAlchemy and the Python multiprocessing module. This is with Python 2.6.6-8+b1(default) and SQLAlchemy 0.6.3-3 (default)

4条回答
  •  醉梦人生
    2021-01-05 07:22

    (This is in answer to Faheem Mitha's question in a comment about how to use copy_reg to work around the broken exception classes.)

    The __init__() methods of SQLAlchemy's exception classes seem to call their base class's __init__() methods, but with different arguments. This mucks up pickling.

    To customise the pickling of sqlalchemy's exception classes you can use copy_reg to register your own reduce functions for those classes.

    A reduce function takes an argument obj and returns a pair (callable_obj, args) such that a copy of obj can be created by doing callable_obj(*args). For example

    class StatementError(SQLAlchemyError):
        def __init__(self, message, statement, params, orig):
            SQLAlchemyError.__init__(self, message)
            self.statement = statement
            self.params = params
            self.orig = orig
        ...
    

    can be "fixed" by doing

    import copy_reg, sqlalchemy.exc
    
    def reduce_StatementError(e):
        message = e.args[0]
        args = (message, e.statement, e.params, e.orig)
        return (type(e), args)
    
    copy_reg.pickle(sqlalchemy.exc.StatementError, reduce_StatementError)
    

    There are several other classes in sqlalchemy.exc which need to be fixed similarly. But hopefully you get the idea.


    On second thoughts, rather than fixing each class individually, you can probably just monkey patch the __reduce__() method of the base exception class:

    import sqlalchemy.exc
    
    def rebuild_exc(cls, args, dic):
        e = Exception.__new__(cls)
        e.args = args
        e.__dict__.update(dic)
        return e
    
    def __reduce__(e):
        return (rebuild_exc, (type(e), e.args, e.__dict__))
    
    sqlalchemy.exc.SQLAlchemyError.__reduce__ = __reduce__
    

提交回复
热议问题