Python программа завершает работу без каких-либо исключений - PullRequest
0 голосов
/ 08 февраля 2020

Недавно я узнал о python декораторах, поэтому я попробовал и спроектировал декоратор так:

def retry(repeat,error_return=None):
    def decorator(function):        
        def wrapper(*args,**kwargs):            
            nonlocal repeat
            while repeat>0:
                try:
                    return function(*args,**kwargs)                    
                except Exception as e:
                    repeat=repeat-1
                    print(e)
            return error_return                
        return wrapper    
    return decorator

Если во время выполнения оформленной функции возникло исключение, исключение не возникнет. И функция будет повторяться в течение определенного времени до того, как будет напечатано исключение.

Я использовал декоратор на простом загрузчике, например:

@retry(3)
def download_single(url,path):
    ........

    content=requests.get(url,timeout=10).content
    with open(path,'w') as f:
        f.write(content)
    print('Downloaded'+path)

def download_all(alist):
    for url in alist:
        download_single(url,PATH)

Обычно, и, как я и ожидал, он должен работать следующим образом: The exception is skipped with error information printed

Однако в некоторых случаях программа просто останавливается после того, как напечатано исключение: image>> left">

Так с какой стати это останавливается само собой ?? (Список URL содержит более 1000 элементов, и он остановился на 37)

И это случалось много раз на разных элементах. Так что это не проблема определенного URL.

И это та же проблема, когда я запускаю программу прямо из консоли. Так что это не потому, что IDLE тоже. run in cmd

Это проблема с декоратором или загрузчиком? Таким образом, он завершается только сразу после исключения, поэтому я думаю, что исключение вызвало тихий выход. Кто-нибудь встречал подобные случаи раньше?

1 Ответ

0 голосов
/ 09 февраля 2020

Я предполагаю, что ваша программа печатает 3 исключения всего , то есть не по URL. Это потому, что вы объявляете repeat как nonlocal и изменяете эту переменную. Оболочка определяет замыкание по этому имени (repeat), поэтому при каждом вызове функции вы получаете доступ к одному и тому же объекту. Это означает, что всякий раз, когда вы вызываете download_single, и он терпит неудачу, он изменяет тот же самый объект repeat. Таким образом, это дает в общей сложности 3 попытки для всей программы вместо одного URL. Тогда repeat равен нулю, а wrapper просто больше не выполняет никакой работы (он напрямую возвращает error_return). Это означает, что ваша программа не завершает свою работу преждевременно, но исчерпывает список всех файлов, не выполняя никакой работы после третьего тайм-аута.

Вместо этого вы можете просто l oop over range(repeat) внутри оболочки:

for __ in range(repeat):
    try:
        return function(*args,**kwargs)                    
    except Exception as e:
        print(e)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...