размещение простых скриптов Python в контейнере для обработки параллелизма, конфигурации, кэширования и т. д. - PullRequest
1 голос
/ 02 июня 2010

Мой первый реальный проект на Python - написать простой каркас (или повторно использовать / адаптировать существующий), который может обернуть небольшие скрипты Python (которые используются для сбора пользовательских данных для инструмента мониторинга) с «контейнером» «для решения стандартных задач, таких как:

  • извлечение конфигурации скрипта из файла (и поддержание этой информации в актуальном состоянии, если файл изменяется и обрабатывает дешифрование конфиденциальных данных конфигурации)
  • запуск нескольких экземпляров одного и того же скрипта в разных потоках вместо запуска нового процесса для каждого
  • предоставляет API для кэширования дорогих данных и сохранения постоянного состояния от одного вызова скрипта до следующего

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

Ниже приведены примеры API, о котором я думал, и о котором я хочу узнать ваши отзывы.

Сценарист должен будет создать один метод, который принимает (в качестве входных данных) конфигурацию, необходимую сценарию для выполнения своей работы, и либо возвращает объект python, либо вызывает метод для потоковой передачи данных в виде фрагментов. При желании сценарий может предоставить методы для обработки задач запуска и / или завершения работы.

Пример сценария HTTP-выборки (в псевдокоде, пропуская фактические данные выборки данных, чтобы сосредоточиться на API контейнера):

def run (config, context, cache) : 
    results = http_library_call (config.url, config.http_method, config.username, config.password, ...) 
    return { html : results.html, status_code : results.status, headers : results.response_headers }

def init(config, context, cache) : 
     config.max_threads = 20  # up to 20 URLs at one time (per process) 
     config.max_processes = 3  # launch up to 3 concurrent processes 
     config.keepalive = 1200  # keep process alive for 10 mins without another call
     config.process_recycle.requests = 1000  # restart the process every 1000 requests (to avoid leaks) 
     config.kill_timeout = 600  # kill the process if any call lasts longer than 10 minutes 

Пример сценария извлечения данных из базы данных может выглядеть так (в псевдокоде):

def run (config, context, cache) : 
    expensive = context.cache["something_expensive"] 
    for record in db_library_call (expensive, context.checkpoint, config.connection_string) : 
        context.log (record, "logDate")  # log all properties, optionally specify name of timestamp property 
        last_date = record["logDate"] 
    context.checkpoint = last_date  # persistent checkpoint, used next time through 

def init(config, context, cache) : 
    cache["something_expensive"] = get_expensive_thing() 

def shutdown(config, context, cache) : 
    expensive = cache["something_expensive"] 
    expensive.release_me()

Является ли этот API соответствующим образом "питоническим", или я должен что-то сделать, чтобы сделать это более естественным для сценария Python? (Я более знаком со сборкой C ++ / C # / Java API, поэтому я подозреваю, что мне не хватает полезных идиом Python.)

Конкретные вопросы:

  • Естественно ли передать объект "config" в метод и попросить вызываемого пользователя установить различные параметры конфигурации? Или есть другой предпочтительный способ сделать это?
  • когда вызываемый объект должен передавать данные обратно своему вызывающему, подходит ли такой метод, как context.log() (см. Выше), или вместо этого я должен использовать yield? (да, это кажется естественным, но я волнуюсь, это было бы у большинства сценаристов)
  • Мой подход требует использования сценариев для определения функций с предопределенными именами (например, «run», «init», «shutdown»). Это хороший способ сделать это? Если нет, то какой другой механизм будет более естественным?
  • Я передаю одинаковые config, context, cache параметры в каждый метод. Было бы лучше использовать один параметр «контекста» вместо этого? Было бы лучше вместо этого использовать глобальные переменные?
  • Наконец, существуют ли библиотеки, которые вы бы порекомендовали сделать таким простым "контейнером для выполнения скриптов", который легче писать?

1 Ответ

0 голосов
/ 02 июня 2010

Взгляните на SQL Alchemy для работы с базами данных в python. Также для облегчения написания сценариев для работы с параллелизмом загляните в Stackless Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...