我正在使用Plex并尝试使用Plex api来获取并不断更新Plex Server的状态。如果状态发生变化,我会做一些事情。这是我的代码(我已经编辑了不相关的部分):
import requests
import time
ip = '127.0.0.1'
port = '####'
def get_status(last_media_type, last_state):
data = requests.get('http://' + ip + ':' + port + '/status/sessions', verify=False)
if home: # Ignore this part. Redacted code
if '<MediaContainer size="0">' in data.text: # If nothing is playing
media_type = 'None'
state = 'STOPPED'
else: # Get what's playing and its status
media_type_start = data.text.find('type=\"')
media_type_end = data.text.find('updatedAt=')
media_type = data.text[media_type_start + 6:media_type_end - 2].capitalize()
print('Type: ' + str(media_type))
state_prefix_start = data.text.find('<Player address=')
state_prefix_end = data.text.find('<TranscodeSession key=')
state_prefix = data.text[state_prefix_start:state_prefix_end]
state_start = state_prefix.find('state=\"')
state_end = state_prefix.find('title=')
state = state_prefix[state_start + 7:state_end - 2].upper()
if last_media_type != media_type or last_state != state: # THIS IS IMPORTANT. I don't want to execute the next part if nothing has changed.
# DO STUFF, redacted
if state == 'PLAYING':
interval = 1
elif state == 'PAUSED':
interval = 10
elif state == 'STOPPED':
interval = 15
else:
interval = 60 * 3 # if nobody home, only check once every 3 minutes
time.sleep(interval)
get_status(media_type, state)
get_status('a', 'b') # filler arguments used to initiate script
问题
不幸的是,半小时后,我得到了:
RecursionError: maximum recursion depth exceeded in comparison
这是追溯(尽管由于编辑而线路编号不匹配):
Traceback (most recent call last):
File "H:/Users/micha/Documents/Scripts/Python/plexStatus.pyw", line 63, in <module>
p = psutil.Process(os.getpid()) # Get PID for this script
File "C:\Python351\lib\site-packages\psutil\__init__.py", line 349, in __init__
self._init(pid)
File "C:\Python351\lib\site-packages\psutil\__init__.py", line 375, in _init
self.create_time()
File "C:\Python351\lib\site-packages\psutil\__init__.py", line 636, in create_time
self._create_time = self._proc.create_time()
File "C:\Python351\lib\site-packages\psutil\_pswindows.py", line 282, in wrapper
return fun(self, *args, **kwargs)
File "C:\Python351\lib\site-packages\psutil\_pswindows.py", line 422, in create_time
if self.pid in (0, 4):
RecursionError: maximum recursion depth exceeded in comparison
问题
如何在没有递归错误的情况下让它工作,而在执行之间只等待1秒钟?
我的猜测是,有一种更好的方法可以调用此脚本,同时仍然可以使用上一次调用中的变量。我无法弄清楚如何。我想我可以使用我已经在另一个编辑部分中使用的pickle
,但是如果可能的话,我想避免大量的读/写。或者真的,只是尽可能减少内存耗费,同时保留功能。
注意: 我确定有更好的解析方法。我是编程新手。在解决这个问题的同时研究这个问题。
我在尝试修复此代码时已经编辑了几次这样的代码,所以我不确定这会不会引发其他错误。这是我试图修复的递归。
我知道有像PlexPy这样的工具。只是尝试自己写一个更小的,我可以连续运行,而不是一个主要的资源猪。
答案 0 :(得分:2)
递归意味着每个函数调用都停留在堆栈上,因此最终会耗尽内存导致RecursionError
。在其他方面有很多方法可以使用“尾调用递归”,就像你已经完成的那样 - except Python will never support this。
运行此操作的最佳方法是修改代码以使其具有无限循环:
def get_status(last_media_type, last_state):
pass # your method here
# except for the recursive call
return state, media_type
last_state = None
last_media_type = 'sensible_default'
while True:
state, media_type = get_status(last_media_type, last_state)
pass # do what you need to compare them here
if last_state != state and last_media_type != media_type:
print "they aren't equal!"
last_state, last_media_type = state, media_type
循环本身(while True:
)几乎不会消耗任何内存,现在不是存储每个过去的状态,而是只有最后一个。
此外,方法调用中的任何信息都是垃圾收集的,因为它会在您的方法返回时丢失范围 - 这是对代码的直接改进,因为在递归调用中没有永远丢失范围所以没有cal得到了收集。
答案 1 :(得分:1)
您可以使用while循环进行无限循环,而不是使用递归。 递归并不是无限的,因为你已经看到 - 递归增加了堆栈,因此是有限的。