Проблема:
Я получаю следующую трассировку и не понимаю, что это значит и как это исправить:
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
- This is the main class, where the program starts.
- Он создает два объекта multiprocessing.Queue, один
work_queue
и одинwrite_queue
. - Он также создает и запускает другие процессы, а затем ждет их завершения.
- ПРИМЕЧАНИЕ: это не расширение multiprocessing.managers.BaseManager()
- MyReaderClass
- This class reads the data from the SQL Server database.
- Он помещает элементы в папку
work_queue
.
- MyWorkerClass
- This is where the work processing happens.
- Он получает элементы из
work_queue
и помещает завершенные элементы вwrite_queue
.
- MyWriterClass
- This class is in charge of writing the processed data back to the SQL Server database.
- Он получает предметы из
write_queue
.
Идея состоит в том, что будет один менеджер, один читатель, один писатель и много работников.
Другие сведения:
Я дважды получаю трассировку в stderr, поэтому я думаю, что это происходит один раз для читателя и один раз для писателя. Мои рабочие процессы создаются нормально, но просто сидим там, пока я не отправлю KeyboardInterrupt, потому что у них ничего нет в файле work_queue
.
И читатель, и писатель имеют собственное соединение с базой данных, созданное при инициализации.
Решение:
Спасибо Марку и Фердинанду Бейеру за их ответы и вопросы, которые привели к этому решению. Они справедливо указали на то, что объект Cursor не может быть обработан, что является методом многопроцессорной обработки для передачи информации между процессами.
Проблема с моим кодом заключалась в том, что MyReaderClass(multiprocessing.Process)
и MyWriterClass(multiprocessing.Process)
оба подключались к базе данных в своих методах __init__()
. Я создал оба этих объекта (т.е. назвал их метод инициализации) в MyManagerClass
, а затем вызвал start()
.
Таким образом, он создаст объекты соединения и курсора, а затем попытается отправить их дочернему процессу через рассол. Мое решение состояло в том, чтобы переместить создание экземпляров объектов соединения и курсора в метод run(), который не вызывается до тех пор, пока дочерний процесс не будет полностью создан.