Python Multiprocessing и доступ к базе данных с PYODBC «небезопасно»?

StackOverflow https://stackoverflow.com/questions/1537809

Вопрос

Проблема:

Я получаю следующий след и не понимаю, что это значит или как его исправить:

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, как отмечена ошибкой маринованного.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top