【问题标题】:Bug in python threadpython线程中的错误
【发布时间】:2016-12-16 14:32:41
【问题描述】:

我有一些 raspberry pi 运行一些 python 代码。有时我的设备将无法签入。其余的 python 代码继续完美运行,但此处的代码退出。我不确定为什么?如果设备无法签入,则应重新启动,但不会。 python 文件中的其他线程继续正常运行。

class reportStatus(Thread):
    def run(self):
        checkInCount = 0
        while 1:
            try:
                if checkInCount < 50:
                    payload = {'d':device,'k':cKey}
                    resp = requests.post(url+'c', json=payload)
                    if resp.status_code == 200:
                        checkInCount = 0
                        time.sleep(1800) #1800
                    else:
                        checkInCount += 1
                        time.sleep(300) # 2.5 min
                else:
                    os.system("sudo reboot")
            except:
                try:
                    checkInCount += 1
                    time.sleep(300)
                except:
                    pass

这些设备可以运行数天和数周,并且每 30 分钟会完美地检查一次,然后它们会突然停止。我的linux 计算机处于只读状态,计算机继续正常工作和运行。我的问题在这个线程中。我认为他们可能无法得到回应,这条线可能是问题

resp = requests.post(url+'c', json=payload)

我不知道如何解决这个问题,任何帮助或建议将不胜感激。

谢谢

【问题讨论】:

  • 修正缩进。
  • 你有任何追溯吗?我不会说 requests 是问题所在,因为在它之后有一个“catch all”异常
  • 复制粘贴导致缩进错误,在python文件中是正确的。
  • 好吧,除非你也在这里改正,否则帮不了你....
  • 我建议您不要只接受所有可能的异常,因为它可能与问题非常相关。只需在 except 块内调用 traceback.print_exc() 即可查看问题所在。一方面,当它尝试重新启动停止 python 进程的SystemExit 时,可能只是被捕获停止重新启动。

标签: python multithreading python-requests


【解决方案1】:

一个裸露的except:pass is a very bad idea

更好的方法是至少记录任何异常:

import traceback

while True:
  try:
    time.sleep(60)
  except:
    with open("exceptions.log", "a") as log:
      log.write("%s: Exception occurred:\n" % datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
      traceback.print_exc(file=log)

然后,当你得到一个异常时,你会得到一个日志:

2016-12-20 13:28:55: Exception occurred:
Traceback (most recent call last):
  File "./sleepy.py", line 8, in <module>
    time.sleep(60)
KeyboardInterrupt

您的代码也有可能挂在sudo rebootrequests.post 上。您可以添加额外的日志来解决您遇到的问题,尽管您已经看到它会重新启动,我怀疑它是 requests.post,在这种情况下您需要添加 timeout (from the linked answer)

import requests
import eventlet
eventlet.monkey_patch()


#...
resp = None
with eventlet.Timeout(10):
    resp = requests.post(url+'c', json=payload)
if resp:
    # your code

【讨论】:

  • 我很肯定代码不会在 sudo 重启时挂起。很好的答案!谢谢!我确信requsts.post 不会偶尔收到回复,并且一直在等待。
【解决方案2】:

您的代码基本上忽略了所有异常。这在 Python 中被认为是一件坏事。

对于您所看到的行为,我能想到的唯一原因是,在 checkInCount 达到 50 后,sudo reboot 引发异常,然后您的程序会忽略该异常,从而使该线程陷入无限循环.

如果您想查看实际发生的情况,请将 printloggging.info 语句添加到代码的所有不同分支中。

或者,删除一揽子 try-except 子句或将其替换为特定内容,例如except requests.exceptions.RequestException

【讨论】:

    【解决方案3】:

    由于给出的答案,我能够想出一个解决方案。我意识到 requests 有一个内置的超时功能。如果未将超时指定为参数,则永远不会发生超时。
    这是我的解决方案:

    resp = requests.post(url+'c', json=payload, timeout=45)
    

    您可以告诉请求在给定的响应之后停止等待响应 带有 timeout 参数的秒数。几乎所有的生产 代码应在几乎所有请求中使用此参数。不做 所以会导致你的程序无限期挂起

    TemporalWolf 和其他人提供的答案对我帮助很大。感谢所有提供帮助的人。

    【讨论】:

    • 内置超时有帮助,但不能防止挂起 - 它是 服务器通信之间的最大等待时间,而不是调用返回的最长时间。
    • 好的。我将使用 eventlet。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    • 1970-01-01
    • 1970-01-01
    • 2013-04-19
    • 2016-01-15
    • 1970-01-01
    • 2012-12-23
    相关资源
    最近更新 更多