我正在为KODI编写脚本,当发生代码错误时,我发现了一个无限循环。此循环意味着我必须登录其他帐户或重新启动计算机才能停止KODI。
因此,我的问题是,如何确保while
在各方面都会停止?
这只是脚本的一部分,代码包含在try
中。如果我提出错误,您还需要知道try
始终有效。
代码中的问题是while
部分,例如在p.get()
。这会导致错误,因为我在调用get()
之前没有检查工作是否已完成(我没有为此纠正此错误)。
问题在于,即使我使用try
,意外错误也会导致while
无法停止!
def browse(separate, page):
[...]
# Getting meta data and subtitles
pools = {'metadata': [], 'subtitles': []}
with closing(multiprocessing.Pool(processes=2)) as pool:
provider_meta = call_provider(PROVIDERS['meta_tmdb'])
provider_subtitle = call_provider(PROVIDERS['subtitle_subscene'])
for item in items:
pools['metadata'].append(pool.apply_async(provider_meta.get, args=(item["info"]["code"], item["label"], item["info"]["year"]), callback=pool_stats))
pools['subtitles'].append(pool.apply_async(provider_subtitle.get, args=(item["info"]["code"], item["label"], item["info"]["year"]), callback=pool_stats))
pool_checklist = _create_checklist(pools)
while not xbmc.abortRequested and not dialog.iscanceled():
xbmc.sleep(100)
# Check if are raise a error
for p in pool_checklist:
p.get()
# Break when all requests are done
if all(p.ready() for p in pool_checklist):
break
else:
return
[...]
def _create_checklist(pools):
plist = []
for c in pools.values():
for p in c:
plist.append(p)
return plist
更新
我不确定while
是否仅受while
中编写的代码影响,或者是否存在可能影响while
进程的其他方面。
更新2
检查 get()
是否返回错误的测试。使用Python 3.x进行测试,而不是使用Python 2.x,这是KODI正在使用的。
更新3
查看get()
是否返回加注错误的测试。使用Python 3.4.2和Python 2.7.10进行测试。
from multiprocessing import Pool
from contextlib import closing
import time
def func(x, i):
if i == 10:
raise Exception('ttt')
return {'x':i}
def go():
try:
def callback(x):
print('done: '+str(x['x']))
pools = []
with closing(Pool(processes=2)) as pool:
for i in range(20):
pools.append(pool.apply_async(func, args=(i,i), callback=callback))
while not all(p.ready() for p in pools):
time.sleep(1)
list = map(lambda p: p.get(), pools)
for l in list:
print(l)
print('Finished with the script')
except:
print('ERROR')
if __name__ == '__main__':
go()
更新4
问题仍然存在:
while
仅受while
中编写的代码影响,或其他方面是否会影响while
流程?while
在各方面都会停止?更新5
似乎没有一个解决方案,while
将在各个方面停止。
因此,我认为简单的解决方案是在while
之后检查池。
def browse(separate, page):
[...]
# Getting meta data and subtitles
pools = {'metadata': [], 'subtitles': []}
with closing(multiprocessing.Pool(processes=2)) as pool:
provider_meta = call_provider(PROVIDERS['meta_tmdb'])
provider_subtitle = call_provider(PROVIDERS['subtitle_subscene'])
for item in items:
pools['metadata'].append(pool.apply_async(provider_meta.get, args=(item["info"]["code"], item["label"], item["info"]["year"]), callback=pool_stats))
pools['subtitles'].append(pool.apply_async(provider_subtitle.get, args=(item["info"]["code"], item["label"], item["info"]["year"]), callback=pool_stats))
pool_checklist = _create_checklist(pools)
while not all(p.ready() for p in pool_checklist):
if xbmc.abortRequested or dialog.iscanceled()
return
xbmc.sleep(100)
# Check the pools for errors
for p in pool_checklist:
p.get()
[...]
def _create_checklist(pools):
plist = []
for c in pools.values():
for p in c:
plist.append(p)
return plist
答案 0 :(得分:0)
错误发生在get()
,但目标位于apply_async()
。因此,该解决方案只能再次停止该过程。
结论是这样的。尽管Pool
出现故障,循环仍将继续,因此您可以随时退出循环。
def browse(separate, page):
[...]
# Getting meta data and subtitles
pools = {'metadata': [], 'subtitles': []}
with closing(multiprocessing.Pool(processes=2)) as pool:
provider_meta = call_provider(PROVIDERS['meta_tmdb'])
provider_subtitle = call_provider(PROVIDERS['subtitle_subscene'])
for item in items:
pools['metadata'].append(pool.apply_async(provider_meta.get, args=(item["info"]["code"], item["label"], item["info"]["year"]), callback=pool_stats))
pools['subtitles'].append(pool.apply_async(provider_subtitle.get, args=(item["info"]["code"], item["label"], item["info"]["year"]), callback=pool_stats))
pool_checklist = _create_checklist(pools)
# Loop
while not all(p.ready() for p in pool_checklist):
if xbmc.abortRequested or dialog.iscanceled():
return
xbmc.sleep(100)
# Check the results for errors
for p in pool_checklist:
p.get()
[...]
此外,对于Python 3.4.2和2.7.10,Pool
只会在完成时引发错误,并且可以使用任何其他的get()
来检查结果是否有错误。