用pyodbc进行Python多处理和数据库访问"不安全"?

tgr*_*ray 12 python sql-server pickle multiprocessing pyodbc

问题:

我得到以下回溯,并不明白它的含义或如何解决它:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Python26\lib\multiprocessing\forking.py", line 342, in main
    self = load(from_parent)
  File "C:\Python26\lib\pickle.py", line 1370, in load
    return Unpickler(file).load()
  File "C:\Python26\lib\pickle.py", line 858, in load
    dispatch[key](self)
  File "C:\Python26\lib\pickle.py", line 1083, in load_newobj
    obj = cls.__new__(cls, *args)
TypeError: object.__new__(pyodbc.Cursor) is not safe, use pyodbc.Cursor.__new__()
Run Code Online (Sandbox Code Playgroud)

情况:

我有一个SQL Server数据库,里面装满了要处理的数据.我正在尝试使用多处理模块来并行化工作并利用计算机上的多个核心.我的一般类结构如下:

  • MyManagerClass
    • 这是程序启动的主类.
    • 它创建了两个multiprocessing.Queue对象,一个work_queue和一个write_queue
    • 它还创建并启动其他进程,然后等待它们完成.
    • 注意:这不是 multiprocessing.managers.BaseManager()的扩展.
  • MyReaderClass
    • 此类从SQL Server数据库中读取数据.
    • 它将物品放入work_queue.
  • MyWorkerClass
    • 这是工作处理发生的地方.
    • 它从中获取项目work_queue并将完成的项目放入write_queue.
  • MyWriterClass
    • 该类负责将处理后的数据写回SQL Server数据库.
    • 它从中获取物品write_queue.

这个想法是将有一位经理,一位读者,一位作家和许多工人.

其他详情:

我在stderr中得到了两次回溯,所以我认为它对于读者来说只发生一次,对作者来说只发生一次.我的工作进程被创建得很好,但只是坐在那里直到我发送一个KeyboardInterrupt,因为他们什么都没有work_queue.

读者和编写者都有自己的数据库连接,在初始化时创建.

解:

感谢Mark和Ferdinand Beyer提供的解决方案和问题.他们理所当然地指出Cursor对象不是"pickle-able",这是多处理用于在进程之间传递信息的方法.

我的代码的问题是,MyReaderClass(multiprocessing.Process)并且MyWriterClass(multiprocessing.Process)都在他们的__init__()方法中连接到数据库.我创建了这两个对象(即称为init方法)MyManagerClass,然后调用start().

所以它会创建连接和游标对象,然后尝试通过pickle将它们发送到子进程.我的解决方案是将连接和游标对象的实例化移动到run()方法,该方法在完全创建子进程之前不会被调用.

Mar*_*ark 11

多处理依赖于酸洗来在进程之间传递对象.pyodbc连接和游标对象无法进行pickle.

>>> cPickle.dumps(aCursor)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.5/copy_reg.py", line 69, in _reduce_ex
    raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle Cursor objects
>>> cPickle.dumps(dbHandle)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.5/copy_reg.py", line 69, in _reduce_ex
    raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle Connection objects
Run Code Online (Sandbox Code Playgroud)

"它将项目放入work_queue",有哪些项目?光标对象是否也可以传递?