web-dev-qa-db-ja.com

「警告conda.gateways.disk:exp_backoff_fn(47):「condainstall」中にerrno41でバックオフがキャッチされませんでした」

今日から私はたくさん得ます

警告conda.gateways.disk:exp_backoff_fn(47):errno41でキャッチされていないバックオフ

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

これらの警告を修正するために私が何をする必要があるか教えていただけますか?または私はそれらを無視できますか?

16
MSeifert

表示されるこれらの警告は、現在のcondaソースツリーによると「正常」です。前述の警告の原因を理解するために、質問のソースコードと、condaリポジトリ( https://github.com/conda/conda )の最近のコミットを見てみましょう。表示される警告を出力する関連ソースコードは次のとおりです。

https://github.com/conda/conda/blob/4.3.4/conda/gateways/disk/init.py

_# -*- 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 を使用して詳細に入ると、errno 41が対応しているようです。に

ENOTEMPTY:ディレクトリが空ではありません

これは、指定されたディレクトリが空ではないことを示します。この種のエラー([〜#〜] enotempty [〜#〜])を処理するブランチがないため、キャッチされないエラーです。 [〜#〜] eperm [〜#〜]または[〜#〜] eacces [〜#〜]のような別のエラーの場合があります
コミット中 https://github.com/conda/conda/commit/fb2a783d9b9371559b5ea82aaf8ae631c2ce0450#diff-3757ed9862260ae3b54768b3e482e3fe
レポートEPROTOTYPEOSError(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.pydelete_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/a26b1eff17dcaf12f03aea5bbe8dee1e01308de7/conda/cli/main_update.py

ご覧のとおり、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%言うことはできませんでした。数回試行した後、ごみ箱ディレクトリを削除するコマンドが成功した場合、問題はありません。しかし、それが成功しない場合は、削除しない結果としてこのディレクトリがどんどん大きくなるという問題が発生します。そのためにリポジトリで開かれた問題はほとんどなく、修正がヒットしたコードパスをカバーしているかどうかはわかりません。私の印象はそうではないかもしれないということです。さらに洞察を得るために、情報ログレベルをアクティブにすることができます。


[〜#〜] update [〜#〜]:この問題 https://github.com/conda/conda/issues/ 4164 すべての再試行のために更新とインストールに時間がかかっていたため、報告した警告を正確に記載してください。すべての再試行(指数関数的なバックオフ)の後、削除操作が成功または失敗する可能性があることを述べたように、その人はレポートでこの側面についても言及しています。
ここでわかるように
https://github.com/conda/conda/issues/3664
再試行による長い待機時間の問題を解決するために人々が採用するハックはほとんどなく、警告なしにコマンドの次の実行も_conda install X_または_conda update X_になります。これらの提案は次のとおりです。

  1. (再試行/削除の時間を短縮するため) conda/gateways/disk /init。pyのコピーに_MAX_TRIES = 1_を設定します
  2. 次の_conda install X_または_conda update X_を実行する前に、.trashディレクトリを削除してください。単純なスクリプトを使用してそのディレクトリの削除を自動化するために一部の人が採用している回避策については、 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)を使用します。


UPDATE 2:私のコメントの1つで述べたように、重要な変更の1つは、「修正」であったファイル_conda/gateways/disk/__init__.py_にあります。 ( https://github.com/conda/conda/commit/6cb3be39aec1c738678ae27b3a264941d08c859a )4.3.6バージョンのconda( 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ブランチに入らないので、この場合はそのメッセージが表示されないことがはっきりとわかります。

14
fedepad

これらの警告は、condaバージョン4.3.4および4.3.5のコンピューターに存在しますが、4.2.xバージョンには存在せず、最新リリース(4.3.6)には存在しません。

問題を「修正」する最善の方法は、condaを更新することだと思います。

$ conda update conda

または4.2にダウングレードするには:

$ conda install conda=4.2

どちらのバージョンでも、警告は消えます。

1
MSeifert