2012-02-07 3 views
5

Мы разрабатываем небольшое серверное приложение. Серверное приложение выполняет некоторую обработку данных и отвечает клиенту. Чтобы часть обработки данных была конфигурируемой и гибкой, мы решили пойти на скриптинг и на основе наличия различных готовых модулей мы решили пойти на Python. Мы используем Python-C api для отправки/получения данных между c и python.Проблема параллелизма Python-C api

Алгоритм работает примерно так: -

  1. Сервер получает некоторые данные от клиента, эти данные хранятся в словаре, созданном в с. Словарь создается с помощью функции api PyDict_New(); от c. Вход хранится как пара значений ключа в словаре, используя функцию api PyDict_SetItemString();
  2. Далее мы выполняем скрипт python PyRun_SimpleString(); передавая скрипт в качестве параметра. Этот скрипт использует словарь, созданный в c. Обратите внимание: мы создаем словарь, созданный в c, доступный скрипту, используя методы PyImport_AddModule(); и PyModule_AddObject();
  3. Мы сохраняем результат обработки данных в скрипте как пару ключевых значений в том же словаре, который был создан выше. Затем код c может просто получить доступ к переменной результата (парам ключ-значение) после выполнения сценария.

Проблема Проблема, которую мы сталкиваемся в случае одновременных запросов, поступающих от разных клиентов. Когда несколько запросов поступают от разных клиентов, мы склонны исключать исключения ссылочного числа ссылок. Обратите внимание, что для каждого запроса, который приходит для пользователя, мы создаем независимый словарь для этого пользователя. Чтобы преодолеть эту проблему, мы включили вызов PyRun_SimpleString(); в PyEval_AcquireLock(); и PyEval_ReleaseLock() ;, но при этом выполнение скрипта является блокирующим вызовом. Поэтому, если сценарий занимает много времени для выполнения, все остальные пользователи также ждут ответа.

Не могли бы вы предложить наилучший возможный подход или указать указатели на то, где мы ошибаемся. Пожалуйста, звоните мне для получения дополнительной информации.

Любая помощь/руководство будет оценено по достоинству.

ответ

1

Возможно, вам не хватает одного из вызовов, упомянутых в this answer.

+0

Спасибо за ссылку Джейн. Кстати, я звонил на эти функции, но он все равно не сработает. – Will

1

Возможно, вы должны прочитать http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock Ваша проблема объясняется в первом абзаце.

Когда вы приобретаете GIL, делайте это вокруг своей непосредственной манипуляции с объектами Python. Вызов PyRun_SimpleString будет обрабатывать GIL внутренне и будет выдавать его на длительные операции или только на все X-инструкции. Однако это НЕ будет действительно многопоточным.

Edit:

Вы должны получить блокировку, и вы должны убедиться, что Python знает, что в другом состоянии резьбы:

// acquire the lock and switch thread state 
PyEval_AcquireLock(); 
PyThreadState_Swap(perThreadState); 

// execute some python code 
PyEval_SimpleString("print 123"); 

// clear the thread state and release the lock 
PyThreadState_Swap(NULL); 
PyEval_ReleaseLock(); 
+0

Привет, Том, спасибо за ответ. Не могли бы вы рассказать о том, что он «НЕ» будет действительно многопоточным?Вы хотите сказать, что сценарии никогда не могут выполняться параллельно? – Will

+0

Существует глобальная блокировка интерпретатора - только одна команда байт-кода python будет выполняться в любой момент времени, независимо от того, сколько потоков существует. Долгосрочные функции, такие как открытие файла, временно блокируют блокировку во время их выполнения, а интерпретатор python периодически отбрасывает блокировку, но в конечном счете в течение одного процесса байт-коды python выполняются последовательно. –

+0

Спасибо за то, что Том. Оцените свое время для ответов. Пожалуйста, подтвердите это: если PyRun_SimpleString выполняется в 2 (или, возможно, n) отдельных потоках «c», он заботится о самом GIL и, следовательно, мне не нужно блокировать или блокировать, прежде чем делать вызов PyRun_SimpleString из любого потока. – Will

1

Я предлагаю вам исследовать multiprocessing модуль.

Смежные вопросы