ПРЕДУПРЕЖДЕНИЕ conda.gateways.disk: exp_backoff_fn (47): Неперехваченный откат с ошибкой 41 во время установки conda

С сегодняшнего дня я получаю много

ПРЕДУПРЕЖДЕНИЕ conda.gateways.disk: exp_backoff_fn (47): Uncaught backoff with errno 41

предупреждения, когда я пытаюсь обновить или установить пакеты с помощью conda install или conda update. Например:

(...) C:\Users\...> conda install numba
Fetching package metadata ...........
Solving package specifications: .

Package plan for installation in environment C:\...:

The following packages will be DOWNGRADED due to dependency conflicts:

    numba: 0.30.0-np111py35_0 --> 0.30.1-np111py35_0

Proceed ([y]/n)? y

numba-0.30.0-np111p35_0 100% |###############################| Time: 0:00:00   2.50 MB/s
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41
WARNING conda.gateways.disk:exp_backoff_fn(47): Uncaught backoff with errno 41

После этого пакеты устанавливаются, но все эти предупреждения указывают на то, что что-то не работает должным образом.

OS: Windows 10 64 bit
conda: 4.3.4

Не могли бы вы сказать, что мне нужно сделать, чтобы исправить эти предупреждения? Или я могу их игнорировать?


person MSeifert    schedule 14.01.2017    source источник


Ответы (2)


Эти предупреждения, которые вы видите, являются "нормальными" в соответствии с текущим деревом исходных кодов conda. Чтобы понять происхождение вышеупомянутых предупреждений, давайте взглянем на исходный код в вопросах и недавнюю фиксацию в репозитории conda (https://github.com/conda/conda). Соответствующий исходный код, выводящий предупреждения, которые вы видите, следующий:

https://github.com/conda/conda /blob/4.3.4/conda/gateways/disk/< sizesinit

# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals

import sys
from errno import EACCES, ENOENT, EPERM, EPROTOTYPE
from logging import getLogger
from os.path import basename
from time import sleep

from ...common.compat import on_win

log = getLogger(__name__)

MAX_TRIES = 7


def exp_backoff_fn(fn, *args, **kwargs):
    """Mostly for retrying file operations that fail on Windows due to virus scanners"""
    max_tries = kwargs.pop('max_tries', MAX_TRIES)
    if not on_win:
        return fn(*args, **kwargs)

    import random
    # with max_tries = 6, max total time ~= 3.2 sec
    # with max_tries = 7, max total time ~= 6.5 sec
    for n in range(max_tries):
        try:
            result = fn(*args, **kwargs)
        except (OSError, IOError) as e:
            log.trace(repr(e))
            if e.errno in (EPERM, EACCES):
                if n == max_tries-1:
                    raise
                sleep_time = ((2 ** n) + random.random()) * 0.1
                caller_frame = sys._getframe(1)
                log.trace("retrying %s/%s %s() in %g sec",
                          basename(caller_frame.f_code.co_filename),
                          caller_frame.f_lineno,
                          fn.__name__,
                          sleep_time)
                sleep(sleep_time)
            elif e.errno in (ENOENT, EPROTOTYPE):
                # errno.ENOENT File not found error / No such file or directory
                # errno.EPROTOTYPE OSError(41, 'The directory is not empty')
                raise
            else:
                log.warn("Uncaught backoff with errno %d", e.errno)
                raise
        else:
            return result

Из приведенного выше исходного кода это похоже на предупреждение в Windows, которое может появиться, когда

повторная попытка файловых операций, которые завершились ошибкой в ​​Windows из-за антивирусных сканеров

Подробное описание с помощью https://msdn.microsoft.com/en-us/library/t3ayayh1.aspx, похоже, что номер ошибки 41 соответствует

ENOTEMPTY: Каталог не пуст

что сигнализирует о том, что указанный каталог не пуст. Это неперехваченная ошибка, потому что у них нет ветки, которая занимается этим типом ошибок (ENOTEMPTY), в то время как, например, у них есть другая ошибка, такая как EPERM или EACCES.
В фиксации
они явно удаляют сообщение EPROTOTYPE как OSError(41, 'The directory is not empty'), поэтому теперь вы видите, что номер ошибки указан как предупреждение

log.warn("Uncaught backoff with errno %d", e.errno)

Другая часть, которую они изменяют, находится в https://github.com/conda/conda/blob/fb2a783d9b9371559b5ea82aaf8ae631c2ce0450/conda/gateways/disk/delete.py в функции delete_trash(), так что теперь, если вы включите информационный журнал, скорее всего, вы увидите строку вроде

«Невозможно полностью очистить корзину% s \ nОсталось% d файлов».

включен

log.info("Unable to fully clean trash directory %s\nThere are %d remaining file(s).",
                 trash_dir, len(files_remaining))  

Теперь delete_trash() вызывается обеими указанными вами командами (установка, обновление):
https://github.com/conda/conda/blob/f4b386476307e3979679957292d4f6e4c581df03/conda/cli/main_install.py
https://github.com/conda/conda/blob/a26b1eff17dcaf12f308eaaa

Как можно видеть, delete_trash() запускается, соответственно, в файлах 'install' и 'update', ранее упомянутых, соответственно, следующими фрагментами кода:

from ..gateways.disk.delete import delete_trash

# some other code ...

def execute(args, parser):
    install(args, parser, 'install')
    delete_trash()

а также

from ..gateways.disk.delete import delete_trash

# some other code ...

def execute(args, parser):
    install(args, parser, 'update')
    delete_trash()  

delete_trash() затем запустит этот кодовый путь через backoff_rmdir() или backoff_unlink(), что в конечном итоге приведет к предупреждению, которое вы видите от exp_backoff_fn(), как было показано ранее.
Итак, подытоживая, основная цепочка вызовов будет

update or install --> delete_trash() --> backoff_rmdir() or backoff_unlink() --> exp_backoff_fn() --> your warning message

В соответствии с модификациями исходного кода, сделанными в репозитории, разработчики считают, что это предупреждение, которое вы можете спокойно игнорировать, потому что эти предупреждения появляются на этапе «очистки» команд обновления или установки, то есть после того, как операция обновления или установки была успешно завершена. выполнено.
Я не могу сказать на 100%, можно ли игнорировать эти предупреждения. Если после нескольких попыток команда на удаление каталога корзины выполнена успешно, проблем нет. Но если это не удастся, вы столкнетесь с проблемой, что этот каталог будет становиться все больше и больше в результате того, что вы не удалите его. В репо для этого было открыто несколько проблем, и я не знаю, охватывают ли исправления путь кода, который вы выбрали. У меня такое впечатление, что может и нет. Чтобы получить дополнительную информацию, вы можете активировать уровень информационного журнала.


ОБНОВЛЕНИЕ: эта проблема https://github.com/conda/conda/issues/4164 точно упомянуть предупреждения, о которых вы сообщили, потому что пользователи получали долгое время обновления и установки из-за всех повторных попыток. Как я уже упоминал, после всех повторных попыток (экспоненциальных откатов) операция удаления может быть успешной или неудачной, этот человек также упомянул этот аспект в своем отчете.
Как вы можете видеть здесь
https://github.com/conda/conda/issues/3664
есть несколько хаков, которые люди используется для решения проблемы длительного ожидания из-за повторных попыток, а также сделает следующий запуск вашей команды conda install X или conda update X без предупреждения. Вот эти предложения:

  1. (для ускорения времени повторных попыток / удаления) установите MAX_TRIES = 1 в вашей копии conda / gateways / disk / init .py
  2. удалите каталог .trash перед запуском следующего conda install X или conda update X. См. https://github.com/conda/conda/issues/3664 для обходного пути. используется некоторыми людьми для автоматизации удаления этого каталога с помощью простых сценариев. Обычно это должно быть безопасно.

Итак, ответы на ваши вопросы будут следующими:
1) Вы можете использовать обходной путь, упомянутый в https://github.com/conda/conda/issues/3664, который использует следующий скрипт PowerShell (и другой скрипт):

$cir = conda info --root
$trash_dir = "$($cir)\pkgs\.trash"
if (Test-Path $trash_dir){
    Remove-Item -Recurse -Force $trash_dir
}
conda --debug update --all --yes --quiet 

чтобы в основном очистить этот каталог .trash;

2) Вы можете спокойно игнорировать предупреждения в том смысле, что они не повлияют на функциональность; проблема в том, что чем больше заполнится .trash, тем больше будет времени и повторных попыток для удаления элементов, поэтому вы столкнетесь с проблемами производительности; как вы упомянули, это своего рода «утечка», но это не влияет на функциональность. Предполагается, что этот каталог будет очищен и удален, поскольку он больше не содержит ненужного мусора. Система попытается удалить его, но, возможно, не сможет это сделать. Так что используйте 1).


ОБНОВЛЕНИЕ 2. Как упоминалось в одном из моих комментариев, одно из ключевых изменений внесено в файл conda/gateways/disk/__init__.py, который представляет собой «исправление» ( https://github.com/conda/conda/commit/6cb3be39aec1c738678ae27b3a264941d08c859a информация о выпуске conda 4.3.6), что устраняет указанное предупреждение.
Ключевой момент не видеть этого предупреждения - значит иметь ветку, которая явно перехватывает и обрабатывает ошибку, описанную ранее. Теперь, когда произойдет ошибка типа ENOTEMPTY (которая в данном случае является ошибкой, которая вызвала печать предупреждения), она будет перехвачена и не перейдет в ветку, которая печатает предупреждение, рассмотренное в вопросе. Чтобы понять основные отличия, в версии 4.3.4 было

elif e.errno in (ENOENT, EPROTOTYPE):                   
     raise
else:
     log.warn("Uncaught backoff with errno %d", e.errno)
     raise

в то время как в версии 4.3.6 он стал:

elif e.errno in (ENOENT, ENOTEMPTY):    
    raise
else:
    log.warn("Uncaught backoff with errno %s %d", errorcode[e.errno], e.errno)
    raise

и вы ясно видите, что теперь эта ошибка не перейдет в ветку else, поэтому вы не увидите это сообщение в этом случае.

person fedepad    schedule 15.01.2017
comment
Не могли бы вы пояснить, почему вы говорите, что можете спокойно игнорировать предупреждение, если оно не может полностью очистить (удалить неиспользуемые и ненужные папки) после установки? Это больше похоже на утечку памяти, но с данными на жестком диске вместо ОЗУ. (Я не знаю, что это за слово в таком случае.) - person MSeifert; 15.01.2017
comment
Я сказал, потому что я не могу гарантировать 100%, если бы вы могли активировать уровень информационного журнала, мы могли бы видеть, видим ли мы строку Невозможно полностью очистить каталог мусора% s \ nПечатано% d оставшихся файлов. Я согласен, это проблема. Не могли бы вы активировать информационный журнал? Помните, что хотя эти попытки потерпели неудачу, это не означает, что все попытки, которые он попытается сделать, потерпят неудачу ... - person fedepad; 15.01.2017
comment
Если я вычищу мусор, предупреждения все равно будут появляться. Однако мусор в основном пуст, поэтому я думаю, что он несколько раз выходит из строя, и в конце концов его удается очистить. Однако, если я вручную изменю MAX_TRIES, корзина не будет очищена. Так что у меня предупреждения и полный хлам. Есть ли другая идея, кроме удаления самого предупреждения, которая могла бы помочь? - person MSeifert; 19.01.2017
comment
Да, я понимаю поведение при установке MAX_TRIES ‹7. Не могли бы вы попробовать заменить файл conda/gateways/disk/__init__.py на этот вот здесь: conda / gateways / disk / __ init__.py и посмотрите, что произойдет? Спасибо! - person fedepad; 19.01.2017
comment
Похоже, что в новейшую версию conda (4.3.6) уже включены исправления для этих предупреждений. Я не тестировал ваш связанный файл (он должен быть из master или 4.3.6, верно?), И я надеюсь, вы не возражаете, что я сам ответил на вопрос. Спасибо за вашу помощь! - person MSeifert; 20.01.2017
comment
Получать десятки таких предупреждений очень неприятно. Я полагаю, пора Конде, чтобы этика выходных данных достигла зрелости. - person Arthur; 21.01.2017

Эти предупреждения присутствовали на моем компьютере с версиями conda 4.3.4 и 4.3.5, но их больше нет в версии 4.2.x и не в последней версии (4.3.6).

Думаю, лучший способ "исправить" проблему - обновить conda:

$ conda update conda

или понизить до 4.2:

$ conda install conda=4.2

В обеих версиях предупреждения исчезают.

person MSeifert    schedule 20.01.2017