Python Multiprocessing и доступ к базе данных с PYODBC «небезопасно»?
-
20-09-2019 - |
Вопрос
Проблема:
Я получаю следующий след и не понимаю, что это значит или как его исправить:
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
- Он также создает и запускает другие процессы, а затем ждет, пока они закончат.
- Примечание: это нет Расширение многопроцессы. Managers.basemanager ()
- MyReaderClass
- Этот класс считывает данные из базы данных SQL Server.
- Он ставит предметы в
work_queue
.
- MyWorkerClass
- Здесь происходит обработка работы.
- Он получает предметы из
work_queue
и ставит заполненные предметы вwrite_queue
.
- Mywriterclass
- Этот класс отвечает за написание обработанных данных обратно в базу данных SQL Server.
- Он получает предметы из
write_queue
.
Идея состоит в том, что будет один менеджер, один читатель, один писатель и многие работники.
Другие детали:
Я получаю Traceback дважды в Stderr, поэтому я думаю, что это происходит один раз для читателя и один раз для писателя. Мои рабочие процессы создаются нормально, но просто сижу там, пока я не отправлю Keyboard Interrupt, потому что у них нет ничего в work_queue
.
И читатель, и писатель имеют свое собственное соединение с базой данных, созданное при инициализации.
Решение:
Спасибо Марку и Фердинанду Бейеру за их ответы и вопросы, которые привели к этому решению. Они по праву указали, что объект курсора не является «маринованным», который является методом, который многопроцессор использует для передачи информации между процессами.
Проблема с моим кодом заключалась в том, что MyReaderClass(multiprocessing.Process)
а также MyWriterClass(multiprocessing.Process)
оба подключены к базе данных в их __init__()
методы Я создал оба эти объекта (т.е. MyManagerClass
, затем вызвано start()
.
Таким образом, это создало бы объекты соединения и курсора, а затем попытается отправить их на дочерний процесс через Pickle. Мое решение состояло в том, чтобы перенести экземпляры объектов соединения и курсора в метод run (), который не вызван до тех пор, пока дочерний процесс не будет полностью создан.
Решение
Многопроцессорная зависимость полагается на марину для передачи объектов между процессами. Подключение PYOODBC и объекты курсора не могут быть заморожены.
>>> 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
«Он помещает элементы в work_queue», какие элементы? Возможно ли, что объект курсора также проходит?
Другие советы
Ошибка поднимается в рамках pickle
Модуль, поэтому где-то, где ваш объект DB-Cursor заманивается и незаметный (сериализируется на хранение и снова не подвергается невозможному объекту Python).
я думаю что pyodbc.Cursor
не поддерживает маринованную. Почему вы должны пытаться сохранить объект курсора в любом случае?
Проверьте, используете ли вы pickle
Где -то в вашей рабочей цепочке или, если она используется, внесение никакого значения.
pyodbc имеет Python DB-API Threadsafety Уровень 1. Анкет Это означает, что потоки не могут делиться подключениями, и это вообще не является Threadsafe.
Я не думаю, что основные драйверы ODBC, безопасные для потока, имеют значение. Это в коде Python, как отмечена ошибкой маринованного.