问题:
我得到以下追溯,但不明白它的含义或解决方法:
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__()
情况:
我有一个SQL Server数据库,里面装满了要处理的数据。我正在尝试使用多处理模块来并行化工作并利用计算机上的多个核心。我的一般班级结构如下:
work_queue
和一个write_queue
work_queue
。work_queue
获取项目,并将完成的项目放入write_queue
。write_queue
。这个想法是会有一位经理,一位读者,一位作家和许多工人。
其他详情:
我在stderr中得到了两次回溯,所以我认为它对读者来说只发生一次,对作者来说只发生一次。我的工作进程被创建得很好,但只是坐在那里直到我发送一个KeyboardInterrupt因为它们在work_queue
中没有任何内容。
读者和编写者都有自己的数据库连接,在初始化时创建。
解决方案:
感谢Mark和Ferdinand Beyer提供的解决方案和问题。他们理所当然地指出Cursor对象不是“pickle-able”,这是多处理用于在进程之间传递信息的方法。
我的代码的问题是MyReaderClass(multiprocessing.Process)
和MyWriterClass(multiprocessing.Process)
都在__init__()
方法中连接到数据库。我在MyManagerClass
中创建了这两个对象(即称为init方法),然后调用start()
。
因此它会创建连接和游标对象,然后尝试通过pickle将它们发送到子进程。我的解决方案是将连接和游标对象的实例化移动到run()方法,该方法在完全创建子进程之前不会被调用。
答案 0 :(得分:10)
多处理依赖于pickle来在进程之间传递对象。 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
“它将项目放入work_queue”,有哪些项目?是否有可能传递光标对象?
答案 1 :(得分:3)
错误是在pickle
模块中引发的,所以你的DB-Cursor对象被某个地方腌制和取消连接(序列化为存储并再次反序列化为Python对象)。
我猜pyodbc.Cursor
不支持酸洗。为什么要尝试保留游标对象呢?
检查您是否在工作链中的某个位置使用pickle
,或者是否使用了隐含的。{/ p>
答案 2 :(得分:1)
pyodbc包含Python DB-API threadsafety level 1。这意味着线程不能共享连接,而且它根本不是线程安全的。
我不认为底层的线程安全的ODBC驱动程序会有所作为。如Pickling错误所述,它位于Python代码中。