Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用pyodbc的Python多处理和数据库访问;“不安全吗?”;?_Python_Sql Server_Multiprocessing_Pickle_Pyodbc - Fatal编程技术网

使用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数据库
    • 它从
      写入队列
      中获取项目
其理念是,将有一名经理、一名读者、一名作家和许多工人

其他详细信息:

我在stderr中得到了两次回溯,所以我认为读者和作者各有一次。我的工作进程创建得很好,但只是坐在那里,直到我发送键盘中断,因为它们在
工作队列中没有任何内容

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

解决方案:

感谢马克和费迪南德·拜尔的回答和提出的问题,最终得出了这个解决方案。他们正确地指出游标对象不是“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(特别是我创建的队列对象)。我只想说:好问题。