У меня есть raspberry pi с raspbian на нем, и я создал скрипт python, который мне нужно запускать все время. Проблема в том, что после часа работы скрипт внезапно останавливается, а процесс python завершается. Я понятия не имею, почему, и я новичок в Linux, поэтому я не знаю, как его отлаживать или что-то в этом роде. Я не думаю, что это проблема памяти, потому что во время цикла while я освобождаю и повторно инициализирую все используемые объекты. Как я могу узнать, в чем проблема, или, по крайней мере, автоматически перезапустить программу после ее остановки?
Это код:
import time
import sys
import ftputil
import pygame
import pygame.camera
import logging
pygame.camera.init()
#pygame.camera.list_camera() #Camera detected or not
cam = pygame.camera.Camera("/dev/video0",(640,480))
count = 5
logging.basicConfig(filename='log.log', level=logging.INFO)
logging.info(str(time.time())+" : Script was started")
while True:
cam.start()
img = cam.get_image()
pygame.image.save(img,"current.jpeg")
cam.stop()
host = ftputil.FTPHost(**)
host.upload("./current.jpeg", "/domains/*/public_html/webcam.jpg", mode='b')
host.close()
if not count:
host = ftputil.FTPHost(**)
filename = str(time.time()) + ".jpg"
host.upload("./current.jpeg", "/webcamarchive/"+filename, mode='b')
host.close()
count = 10
logging.info(str(time.time())+": Still running")
count -= 1
time.sleep(3)
Скрипт запускаю по ssh. Но я бы хотел, чтобы он запускался и при запуске компьютера, как бы мне это сделать?
1 ответ
Давайте не будем беспокоиться о том, чтобы он запускался каждый раз при запуске вашего компьютера, пока вы не сможете заставить его работать непрерывно в обычном сеансе входа в систему.
Если вы ssh
заходите в компьютер и запускаете его, просто оставьте сеанс ssh
открытым и посмотрите, что он распечатает. Если вы не можете сделать это по какой-либо причине, запишите результат, например, python foo.py >foo.out 2>foo.err
вместо простого python.py
. В любом случае вы сможете увидеть, почему он остановлен, вместо того, чтобы просто знать, что он остановлен.
Вам также следует взглянуть на файл log.log
, который вы явно создаете в своем коде, и на системные журналы (/var/log/syslog
по умолчанию в большинстве дистрибутивов Linux), чтобы увидеть, есть ли там что-нибудь подходящее.
Также, пожалуйста, расскажите нам, как вы «запускаете [ning] скрипт из ssh». Если вы создаете фон с помощью &
, отправляете его как команду ssh
и т. Д., Приведенные выше инструкции необходимо изменить. (Но вам не нужно ждать измененной версии - только на этот раз, ssh
в обычном сценарии входа в систему, запустите его без фонового режима и оставьте работающим.)
Имея только ту информацию, которую вы нам предоставили, невозможно точно знать, что происходит. Но мое первое предположение заключается в том, что вы получаете необработанное исключение, которое вы бы увидели как трассировку исключения, примерно так:
Traceback (most recent call last):
File "exc.py", line 7, in <module>
foo()
File "exc.py", line 5, in foo
print(1/x)
ZeroDivisionError: integer division or modulo by zero
Исправление состоит в том, чтобы справиться с этим. Самое тривиальное исправление выглядит примерно так:
while True:
try:
cam.start()
img = cam.get_image()
pygame.image.save(img,"current.jpeg")
cam.stop()
host = ftputil.FTPHost(**)
host.upload("./current.jpeg", "/domains/*/public_html/webcam.jpg", mode='b')
host.close()
if !count:
host = ftputil.FTPHost(**)
filename = str(time.time()) + ".jpg"
host.upload("./current.jpeg", "/webcamarchive/"+filename, mode='b')
host.close()
count = 10
logging.info(str(time.time())+": Still running")
count -= 1
except Exception as e:
logging.error('Caught exception: ' + str(e))
time.sleep(3)
Тем не менее, вам, вероятно, лучше просмотреть каждый вид исключения, с которым вы можете столкнуться, или просмотреть исключение, с которым вы действительно столкнулись, и поместить соответствующую обработку ошибок и регистрацию в каждом месте, а также только используя это как последний запасной вариант.
Кроме того, вам действительно следует использовать предложения with
вместо ручных вызовов close
. Например, если host.upload()
рейзит, host.close()
никогда не получит колл. Итак, вместо этого:
host = ftputil.FTPHost(**)
host.upload("./current.jpeg", "/domains/*/public_html/webcam.jpg", mode='b')
host.close()
Сделай это:
with contextlib.closing(ftputil.FTPHost(**)) as host:
host.upload("./current.jpeg", "/domains/*/public_html/webcam.jpg", mode='b')
(Многим типам даже не нужен closing
, потому что они уже изначально являются менеджерами контекста, поэтому сначала попробуйте это, но если вы получите ошибку о том, что ftputil.FTPHost
не имеет __enter__
или __exit__
, вот как ты с этим справишься.)
Похожие вопросы
Новые вопросы
python
Python — это мультипарадигмальный многоцелевой язык программирования с динамической типизацией. Он предназначен для быстрого изучения, понимания и использования, а также обеспечивает чистый и унифицированный синтаксис. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Если у вас есть вопросы о версии Python, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas, NumPy) укажите это в тегах.
cam.get_image()
илиhost.upload()
или что-то еще, не может вызвать исключение?if !count:
- этоSyntaxError
в Python. Скрыть параметрыFTPHost
- это нормально (хотя было бы еще лучше проверить, актуален ли он, и полностью удалить все FTP-файлы, если вы все еще можете воспроизвести проблему без него). Но насколько это возможно, постарайтесь опубликовать код, который действительно работает и демонстрирует проблему, которую вы пытаетесь проверить.