Проблема:
Я получаю следующую трассировку и не понимаю, что это значит или как это исправить:
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, заполненная данными для обработки. Я пытаюсь использовать многопроцессорный модуль для распараллеливания работы и использования преимуществ нескольких ядер на моем компьютере. Моя общая структура классов выглядит следующим образом:
- MyManagerClass
- Это основной класс, с которого начинается программа.
- Создает два объекта многопроцессорной обработки. Один
work_queue
и один write_queue
- Он также создает и запускает другие процессы, а затем ожидает их завершения.
- ПРИМЕЧАНИЕ: это , а не расширение многопроцессорной обработки. Менеджеры. BaseManager ()
- MyReaderClass
- Этот класс считывает данные из базы данных SQL Server.
- Это помещает предметы в
work_queue
.
- MyWorkerClass
- Здесь происходит обработка работы.
- Он получает предметы из
work_queue
и кладет завершенные предметы в write_queue
.
- MyWriterClass
- Этот класс отвечает за запись обработанных данных обратно в базу данных SQL Server.
- Получает предметы от
write_queue
.
Идея состоит в том, что будет один менеджер, один читатель, один писатель и много работников.
Другие детали:
Я получаю трассировку дважды в stderr, так что я думаю, что это происходит один раз для читателя и один раз для автора. Мои рабочие процессы создаются нормально, но просто сидите там, пока я не отправлю KeyboardInterrupt, потому что они ничего не имеют в work_queue
.
И читатель, и писатель имеют собственное подключение к базе данных, созданной при инициализации.
Решение:
Спасибо Марку и Фердинанду Бейеру за их ответы и вопросы, которые привели к этому решению. Они справедливо отметили, что объект Cursor не является «способным к расслаиванию», что является методом, который многопроцессорный использует для передачи информации между процессами.
Проблема с моим кодом заключалась в том, что MyReaderClass(multiprocessing.Process)
и MyWriterClass(multiprocessing.Process)
оба подключались к базе данных в своих __init__()
методах. Я создал оба этих объекта (то есть вызвал их метод init) в MyManagerClass
, затем назвал start()
.
Таким образом, он создает объекты соединения и курсора, а затем пытается отправить их в дочерний процесс с помощью pickle. Моим решением было перенести создание экземпляров объектов подключения и курсора в метод run (), который не вызывается до тех пор, пока дочерний процесс не будет полностью создан.