Reputation: 273
I have a raspberry pi with raspbian on it, and I've created a python script that I need to have running all the time. The problem is that after running for an hour or so, the script suddenly stops, and the python process shuts down. I have no idea why, and I'm very new to linux so I don't know how to debug it or anything. I don't think it's a memory issue because during the while loop I free and reinit all objects used. How can I find out what the issue is, or at least automatically restart the program once it stops?
This is the code:
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)
I run the script from ssh. But I would like to make it start when the computer starts up, as well, how would I do this?
Upvotes: 2
Views: 15353
Reputation: 365905
Let's not worry about getting it to run every time your computer starts up until you can get it to run continuously in a normal login session.
If you're ssh
ing into the computer and starting it, just leave the ssh
session open, and watch what it prints out. If you can't do that for whatever reason, capture the output by doing, e.g., python foo.py >foo.out 2>foo.err
instead of just python.py
. Either way, you'll be able to see why it's stopped, instead of just knowing that it's stopped.
You should also look at the log.log
file that you explicitly create in your code, and at the syslogs (/var/log/syslog
by default on most linux distros), to see if there's anything relevant there.
Also, please tell us exactly how you're "run[ning] the script from ssh". If you're backgrounding it with &
, sending it as the ssh
command, etc., the instructions above need to be modified. (But you don't have to wait for the modified version—just this once, ssh
into a normal login script, run it without backgrounding, and leave it running.)
With only the information that you've given us so far, it's impossible to know exactly what's going on. But my first guess is that you're getting an unhandled exception, which you'd see as an exception traceback, something like this:
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
The fix is to handle it. The most trivial fix is something like this:
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)
However, you're probably better off looking over each kind of exception you could run into—or looking at the exception you actually are running into—and putting the appropriate error handling and logging in each place, and only using this as a last-ditch fallback.
Also, you should really use with
clauses instead of manual close
calls. For example, if host.upload()
raises, the host.close()
will never get called. So, instead of this:
host = ftputil.FTPHost(**)
host.upload("./current.jpeg", "/domains/*/public_html/webcam.jpg", mode='b')
host.close()
Do this:
with contextlib.closing(ftputil.FTPHost(**)) as host:
host.upload("./current.jpeg", "/domains/*/public_html/webcam.jpg", mode='b')
(Many types don't even need the closing
, because they're already inherently context managers, so try that first—but if you get an error about ftputil.FTPHost
not having an __enter__
or __exit__
, this is how you can deal with it.)
Upvotes: 3