使用pyodbc的Python多处理和数据库访问;“不安全吗?”;?
问题: 我得到了以下回溯,不明白这意味着什么或如何修复它:使用pyodbc的Python多处理和数据库访问;“不安全吗?”;?,python,sql-server,multiprocessing,pickle,pyodbc,Python,Sql Server,Multiprocessing,Pickle,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"
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__()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“C:\Python26\lib\multiprocessing\forking.py”,第342行,在main中
self=加载(从父级)
加载文件“C:\Python26\lib\pickle.py”,第1370行
返回Unpickler(file.load())
加载文件“C:\Python26\lib\pickle.py”,第858行
调度[键](自身)
文件“C:\Python26\lib\pickle.py”,第1083行,在load\u newobj中
obj=cls.\uuuuu新的\uuuuuu(cls,*args)
TypeError:object.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
情况:
我有一个SQL Server数据库,里面装满了要处理的数据。我正在尝试使用多处理模块来并行化工作,并利用计算机上的多核。我的班级结构如下:
- MyManagerClass
- 这是主类,程序从这里开始
- 它创建两个多处理队列对象,一个
和一个工作队列
写入队列
- 它还创建并启动其他进程,然后等待它们完成
- 注意:这不是multiprocessing.managers.BaseManager()的扩展
- MyReaderClass
- 此类从SQL Server数据库读取数据
- 它将项目放入
工作队列
- 我的工人阶级
- 这就是工作处理发生的地方
- 它从
中获取项目,并将完成的项目放入工作队列
写入队列
- MyWriterClass
- 此类负责将处理后的数据写回SQL Server数据库
- 它从
中获取项目写入队列
工作队列中没有任何内容
读写器都有自己的数据库连接,在初始化时创建
解决方案:
感谢马克和费迪南德·拜尔的回答和提出的问题,最终得出了这个解决方案。他们正确地指出游标对象不是“pickle-able”,这是多处理用来在进程之间传递信息的方法
我的代码的问题是MyReaderClass(multiprocessing.Process)
和MyWriterClass(multiprocessing.Process)
都通过\uuu init\uuuu()方法连接到数据库。我在MyManagerClass
中创建了这两个对象(即称为它们的init方法),然后调用start()
因此,它将创建连接和游标对象,然后尝试通过pickle将它们发送到子进程。我的解决方案是将connection和cursor对象的实例化移动到run()方法,直到完全创建子进程后才调用该方法。错误在pickle
模块中引发,因此在某个地方,DB cursor对象被pickle和unpickle(序列化到存储,并再次取消序列化到Python对象)
我猜pyodbc.Cursor
不支持pickle。为什么还要尝试持久化Cursor对象
检查是否在工作链中的某个位置使用了pickle
,或者它是否被隐式使用。多处理依赖于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
cPickle.dumps(aCursor)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/usr/lib64/python2.5/copy_reg.py”,第69行,在
raise TypeError,“无法pickle%s对象”%base.\u\n__
TypeError:无法pickle游标对象
>>>cPickle.dumps(dbHandle)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/usr/lib64/python2.5/copy_reg.py”,第69行,在
raise TypeError,“无法pickle%s对象”%base.\u\n__
TypeError:无法pickle连接对象
“它将项目放入工作队列”,什么项目?光标对象是否也可能被传递?具有Python DB-API。这意味着线程无法共享连接,并且根本不具有线程安全性
我不认为底层的线程安全ODBC驱动程序有什么区别。正如Pickling错误所指出的,它在Python代码中。我有一个生成器,可以在游标中的项目上循环(基本上称为pyodbyc.cursor().fetchone())。我相信它会产生一个元组(id,stuff\u to\u进程)这就是我放在队列中的内容。我尝试制作了一个deepcopy,但没有成功。我查看了帮助,它实际上是一个Row对象的实例。因此,我可能需要首先转换为元组。Row对象必须包含对光标或其他对象的引用。可能是因为我在MyManagerClass中创建了读写器,以及Connectionon/cursor是在_init__()中创建的,所以从技术上讲,它们是在manager进程中创建的,然后通过管道传输到它们自己的子进程?我将尝试将连接的实例化移动到Run方法。是否有一个解决方法来清除不可pickel?今天,我遇到了一个类似的问题。看起来多进程隐式地使用它在进程之间通过管道对象传递内容s(特别是我创建的队列对象)。我只想说:好问题。