У меня есть 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
GrixM 22 Дек 2012 в 03:27
Вы запускаете сценарий как пользователь в оболочке bash?
 – 
orokusaki
22 Дек 2012 в 03:29
Есть ли что-нибудь в ваших системных журналах из сценария или процесса?
 – 
abarnert
22 Дек 2012 в 03:29
Кроме того, здесь нет никакой обработки ошибок. Вы уверены, что ни одна из вызываемых вами функций, таких как cam.get_image() или host.upload() или что-то еще, не может вызвать исключение?
 – 
abarnert
22 Дек 2012 в 03:30
1
Наконец, я почти уверен, что это не ваш реальный код, потому что if !count: - это SyntaxError в Python. Скрыть параметры FTPHost - это нормально (хотя было бы еще лучше проверить, актуален ли он, и полностью удалить все FTP-файлы, если вы все еще можете воспроизвести проблему без него). Но насколько это возможно, постарайтесь опубликовать код, который действительно работает и демонстрирует проблему, которую вы пытаетесь проверить.
 – 
abarnert
22 Дек 2012 в 03:37
! было изменением в последнюю минуту, я не тестировал его, я просто предположил, что вы написали это на python, я не привык к этому языку. Кроме того, как я уже сказал, я новичок в Linux, как я могу проверить системные журналы? И нет, я не уверен, что эти функции не могут вызвать исключение, но я действительно не знаю, как это проверить.
 – 
GrixM
22 Дек 2012 в 13:25

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__, вот как ты с этим справишься.)

3
abarnert 27 Дек 2012 в 23:40
Спасибо, как видите, я новичок в этом языке, я даже не знал о «с» и «попробовать». Я попробую это и доложу
 – 
GrixM
22 Дек 2012 в 13:28