понедельник, 6 июня 2011 г.

Мелкие грабли при работе с PyWin32

Первые грабли


Возникла необходимость написать простую службу Windows. Для этой цели была избрана известная библиотека PyWin32. На просторах интернета было найдено несколько релевантных примеров и быстренько слеплена служба. Тут я напоролся на первую проблему.

Симптомы
Служба устанавливается, но не запускается. Функция win32serviceutil.StartService падает с исключением win32service.error со следующими значениями:
  • strerror: 'Служба не ответила на запрос своевременно.' ('The service did not respond to the start or control request in a timely fashion.')
  • winerror: 1053
В системном логе (EventLog) в журнале Система (System) видим следующие ошибки:
  • Event 7000, Сбой при запуске службы "Имя_службы" из-за ошибки: Служба не ответила на запрос своевременно.(The Service_Name service failed to start due to the following error: The service did not respond to the start or control request in a timely fashion.)
  • Event 7009, Превышение времени ожидания (30000 мс) при ожидании подключения службы "Имя_службы". (A timeout was reached (30000 milliseconds) while waiting for the Service_Name service to connect.)
При этом никакой паузы, равной указанному таймауту, между попыткой запуска службы и возникновением ошибки не наблюдается. К сожалению, сообщения совершенно не наводят на причину неработоспособности службы.
Причина
Для создания службы PyWin32 использует менеджер Python-служб Lib\site-packages\win32\pythonservice.exe. Естественно, для работы ему нужен интерпретатор питона, в моем случае python26.dll. Гуру подсказали попробовать запустить pythonservice.exe напрямую и посмотреть на результат. В результате я получил сообщение 'The program can't start because python26.dll is missing from your computer. Try reinstal the program to fix this problem.', причина сразу стала ясна. Очевидно, что не получается найти интерпретатор при попытке его загрузки.
Решение
  1. Поместить python26.dll в директорию, где система гарантированно ищет динамические библиотеки, например Windows\System32
  2. Прописать директорию, где находится python26.dll, в переменную среды PATH
В качестве проверки можно снова запустить pythonservice.exe, должны получить в консоли подобное сообщение:
p - Python Service Manager
Options:
 -register - register the EXE - this should generally not be necessary.
 -debug servicename [parms] - debug the Python service.

NOTE: You do not start the service using this program - start the
service using Control Panel, or 'net start service_name'

Теперь все в порядке, служба должна запуститься.

Вторые грабли


Но на этом мои злоключения не закончились. Естественно мне захотелось направлять вывод службы не только куда-нибудь в файл, но и в специально для этого предназначенное системное место - EventLog. Для этого в стандартном модуле logging есть специально обученный обработчик вывода NTEventLogHandler, который по умолчанию требует установленного PyWin32. Одновременно я использовал и FileHandler для параллельного вывода в файл.
Симптомы
Вот тут и ждала меня неожиданность - в EventLog ничего не выводилось. В файле лога новые записи исправно появлялись, а в системном логе - нет.
Причина
Причина оказалась одновременно простой и странной - вывод в EventLog отсутствует, если в имени логгера есть апострофы ('). Это было неожиданно. Времени экспериментировать не было, возможно не только апострофы порождают проблему.
Решение
Решение очевидно - не используйте апострофы в именах логгеров.

Комментариев нет:

Отправить комментарий