问题:
我收到以下回溯,但不明白它的含义或如何解决它:
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 数据库。我正在尝试使用多处理模块来并行化工作并利用我计算机上的多个内核。我的一般班级结构如下:
- 我的管理器类
- 这是程序开始的主类。
- 它创建了两个 multiprocessing.Queue 对象,一个
work_queue
和一个write_queue
- 它还创建并启动其他进程,然后等待它们完成。
- 注意:这不是multiprocessing.managers.BaseManager() 的扩展
- 我的读者类
- 此类从 SQL Server 数据库中读取数据。
- 它将项目放在
work_queue
.
- 我的工人阶级
- 这是工作处理发生的地方。
- 它从 中获取项目
work_queue
并将完成的项目放入write_queue
.
- 我的作家类
- 该类负责将处理后的数据写回 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() 方法,直到子进程完全创建后才会调用该方法。