0

Как запустить Python-скрипт аналогично pm2 для Node.js

16

Проблема с перезапуском скрипта Python на EC2

Я использую pm2 для управления своим скриптом на Node.js и мне это очень нравится. Теперь у меня есть скрипт на Python, который собирает потоковые данные на EC2. Иногда скрипт аварийно завершает работу, и мне нужен менеджер процессов, который бы перезапускал его автоматически, как делает pm2.

Существует ли что-то подобное pm2 для Python? Я искал, но не нашёл ничего подходящего.

Вот ошибка, с которой я столкнулся:

  File "/usr/local/lib/python2.7/dist-packages/tweepy/streaming.py", line 430, in filter
    self._start(async)
  File "/usr/local/lib/python2.7/dist-packages/tweepy/streaming.py", line 346, in _start
    self._run()
  File "/usr/local/lib/python2.7/dist-packages/tweepy/streaming.py", line 286, in _run
    raise exception
AttributeError: 'NoneType' object has no attribute 'strip'
/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/util/ssl_.py:90:

Это простой скрипт для сбора данных:

class StdOutListener(StreamListener):

    def on_data(self, data):
        mydata = json.loads(data)
        db.raw_tweets.insert_one(mydata)
        return True

    def on_error(self, status):
        mydata = json.loads(status)
        db.error_tweets.insert_one(mydata)


if __name__ == '__main__':

    # Это обрабатывает аутентификацию Twitter и подключение к Twitter Streaming API
    l = StdOutListener()
    auth = OAuthHandler(consumer_key, consumer_secret)
    auth.set_access_token(access_token, access_token_secret)
    stream = Stream(auth, l)

    # Эта строка фильтрует потоки Twitter, чтобы захватить данные по ключевым словам: 'python', 'javascript', 'ruby'
    stream.filter(follow=[''])

Я хотел бы, чтобы скрипт сам перезапускался, если что-то пойдёт не так.

5 ответ(ов)

1

Вы действительно можете запускать скрипты на Python из pm2 следующим образом:

pm2 start echo.py

Если ваш скрипт имеет суффикс .py, pm2 будет использовать интерпретатор Python по умолчанию. Если же имя вашего файла не заканчивается на .py, вы можете сделать так:

pm2 start echo --interpreter=python

Я заметил, что нужно быть осторожным с тем, какой именно Python вы используете, особенно если вы работаете в виртуальной среде (virtualenv) с версией Python, отличной от 'умолчательной' версии на вашем компьютере.

0

Ваш вопрос вполне понятен. Вы создали файл конфигурации ecosystem.config.json, в котором описаны ваши приложения, и хотите запустить его с помощью PM2.

Вот пример вашего файла конфигурации:

{
    "apps": [{
        "name": "app_name",
        "script": "/the/app/path/my_app.py",
        "args": ["-c", "my_config.prod.json"],
        "instances": "1",
        "wait_ready": true,
        "autorestart": false,
        "max_restarts": 5,
        "interpreter": "/path/to/venv/bin/python"
    }]
}

Согласно вашему примеру, вы запускаете PM2 с помощью команды:

$ pm2 start ecosystem.config.json
$ pm2 -v
3.2.8

Если у вас возникли проблемы при запуске, вот несколько рекомендаций:

  1. Проверка пути до интерпретатора: Убедитесь, что указанный путь /path/to/venv/bin/python действительно существует и что это правильный интерпретатор Python, используемый для вашего приложения.

  2. Права доступа: Убедитесь, что у вас есть необходимые права доступа к файлу my_app.py и к конфигурационному файлу my_config.prod.json.

  3. Логи ошибок: Проверьте логи ошибок PM2 с помощью команды pm2 logs. Это может дать подсказки о том, почему приложение не запускается.

  4. Версия PM2: У вас установлена версия PM2 3.2.8, которая может быть устаревшей. Возможно, имеет смысл обновить PM2 до последней версии. Это можно сделать с помощью команды:

    npm install pm2@latest -g
    

Попробуйте эти шаги, если столкнетесь с проблемами, и дайте знать, если потребуется помощь с конкретной ошибкой!

0

PM2 вполне достаточно, он будет запускать интерпретатор по суффиксу файла. Вот пример конфигурации:

{
  ".sh": "bash",
  ".py": "python",
  ".rb": "ruby",
  ".coffee": "coffee",
  ".php": "php",
  ".pl": "perl",
  ".js": "node"
}

Таким образом, PM2 автоматически определит, какой интерпретатор использовать в зависимости от расширения файла вашего скрипта. Это значительно упрощает процесс настройки и управления процессами.

0

Если вы пытаетесь запустить программу на Python с использованием pipenv, попробуйте настроить pm2.config.json (или ecosystem.json.config, как указано в официальной документации PM2) следующим образом:

Обратите внимание на важные части: "interpreter" : "pipenv" и "interpreter_args": "run python3".

pm2.config.json:

{
    "apps": [{
        "name": "BackupService",
        "script": "/home/service-backup/service/server.py",
        "args": [""],
        "wait_ready": true,
        "autorestart": false,
        "max_restarts": 5,
        "interpreter" : "pipenv",
        "interpreter_args": "run python3"
    }]
}

После этого выполните команду pm2 start pm2.config.json. Я всегда выполняю pm2 delete BackupService (или то, как вы его назвали в поле "name"), перед повторным запуском, так как даже с флагом --update-env он не использует обновленную pm2.config.json. Почему именно так - не знаю.

Также обратите внимание, что, согласно последней документации PM2, "interpreter_args" могло поменяться на "node_args". Я использую версию pm2 --version 3.0.0, и старый способ всё еще работает.


Если вы хотите запустить программу на Python, использующую библиотеку multiprocessing, решение заключается в том, чтобы принудительно запустить её в fork режиме. PM2, если ему не указать иное, автоматически пытается запустить программу в cluster режиме.

Однако, я подозреваю, что необходимо полностью оставить управление multiprocessing на Python. Мне трудно представить, что PM2 сможет управлять множеством процессов, порождаемых Python, когда работает в cluster режиме. Кроме того, если вы используете опцию "interpreter" (например, для pipenv), только fork_mode будет работать, согласно документации PM2.

Таким образом, добавьте "exec_mode": "fork" в ваш pm2.config.json, чтобы запустить его в нужном режиме.

Если вы не используете файл pm2.config.json, передача -i 0 в команду pm2 start также должна принудить запуск в fork режиме. (-i обозначает количество экземпляров).

0

UPD: Смотрите ответы ниже для более оптимальных решений.

Существует несколько решений для данной задачи. Во-первых, вы можете воспользоваться supervisord, который является достойной универсальной системой контроля процессов и предлагает множество функций "из коробки", таких как автоматический перезапуск, счетчик перезапусков, логирование, гибкая конфигурация и многое другое.

Кроме того, вы можете просто обернуть вашу реализацию в функцию, запустить её в блоке try except, перехватить все исключения и, когда произойдет исключение, вызвать функцию снова вместо выхода из скрипта. В вашем случае такая функция могла бы включать в себя создание слушателя, аутентификацию и работу с потоками.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь