如何确保在各个方面停止

时间:2015-06-25 11:59:07

标签: python xbmc kodi

我正在为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

1 个答案:

答案 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()来检查结果是否有错误。