【问题标题】:Python script stopping after a whilePython脚本在一段时间后停止
【发布时间】:2012-12-09 12:38:57
【问题描述】:

我有一个带有 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 运行脚本。但是我也想让它在计算机启动时启动,我该怎么做呢?

【问题讨论】:

  • 您是否在 bash shell 中以用户身份运行脚本?
  • 您的系统日志中是否有任何内容,无论是来自脚本还是关于进程?
  • 另外,这里绝对没有错误处理。您确定您调用的任何函数(例如 cam.get_image()host.upload() 或其他任何函数)都不会引发异常吗?
  • 最后,我很确定这不是您的实际代码,因为if !count: 在 Python 中是 SyntaxError。隐藏FTPHost 参数很好(尽管测试它是否相关,如果您仍然可以在没有它的情况下重现问题,则完全删除所有 FTP 内容,会更好)。但请尽可能尝试发布实际运行的代码并展示您尝试测试的问题。
  • 该!是最后一分钟的更改,我没有测试它,我只是假设这就是你用 python 编写的方式,我不习惯那种语言。另外,正如我所说我对 linux 很陌生,我如何检查系统日志?不,我不确定这些函数不会引发异常,但我真的不知道如何检查。

标签: python linux crash cron debian


【解决方案1】:

让我们不必担心每次计算机启动时都会运行它,直到您可以让它在正常登录会话中连续运行。

如果您正在 ssh 进入计算机并启动它,只需将 ssh 会话保持打开状态,然后观察它打印出来的内容。如果您出于某种原因无法做到这一点,请通过执行来捕获输出,例如,python foo.py >foo.out 2>foo.err 而不仅仅是 python.py。无论哪种方式,您都可以看到为什么它停止了,而不仅仅是知道它已经停止了。

您还应该查看您在代码中显式创建的 log.log 文件和系统日志(大多数 Linux 发行版上默认为 /var/log/syslog),看看那里是否有任何相关内容。

另外,请准确地告诉我们如何您“从 ssh 运行 [ning] 脚本”。如果您使用& 将其作为后台,将其作为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__ 的错误,这就是你可以处理的方式。)

【讨论】:

  • 谢谢,你可以看到我对这门语言很陌生,我什至不知道“with”和“try”。我会试试这个并报告
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-21
  • 2018-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多