E tenacity.RetryError: RetryError [ ] - PullRequest
       5

E tenacity.RetryError: RetryError [ ]

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

Я застрял с этим в течение нескольких дней, пока не смог найти никакого решения, если есть какие-либо python эксперты, пожалуйста, помогите мне.

Я получаю данные от azure api, в данном случае получаем объект машины, который имеет информацию об этом компьютере.

Сначала у меня есть эта функция, которая возвращает мне ComputeManagementClient с кредитами:

def get_azure_compute_client():
    creds, subscription = get_azure_credentials()
    if "az_compute_client" not in g:
        g.az_compute_client = ComputeManagementClient(creds, subscription)
    return g.az_compute_client

Затем у меня есть Функция, которая использует этот клиент для получения машинного объекта:

@retry(stop=stop_after_attempt(3))
@cache.memoize(60)
def get_azure_machine_info(rg_name, machine_name, expand="instanceView"):

    try:
        compute_client = get_azure_compute_client()
        return (compute_client.virtual_machines.get(rg_name, machine_name, expand=expand))

    except CloudError:
        return None

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

Это мой тестовый пример:

@patch("dev_maintenance.machines.get_azure_compute_client")
def test_get_azure_machine_info (get_azure_compute_client):


    with app.app_context():
        ret = get_azure_machine_info("rg1", "m1")
        assert len(get_azure_compute_client.return_value.method_calls) == 1
        assert (ret == get_azure_compute_client.return_value.machines.virtual_machines.get.return_value)
        get_azure_compute_client.return_value.virtual_machines.get.assert_called_once_with(
            "rg1", "m1", expand="instanceView")

Ошибка:

self = <Retrying object at 0x10641e310 (stop=<tenacity.stop.stop_after_attempt object at 0x10637c790>, wait=<tenacity.wait.wa...bject at 0x1063adf50>, before=<function before_nothing at 0x10639d320>, after=<function after_nothing at 0x1063b0680>)>
fn = <function get_azure_machine_info at 0x10641d680>, args = ('rg1', 'm1'), kwargs = {}, retry_state = <tenacity.RetryCallState object at 0x106552ad0>, do = <tenacity.DoAttempt object at 0x106552b90>

    def call(self, fn, *args, **kwargs):
        self.begin(fn)

        retry_state = RetryCallState(
            retry_object=self, fn=fn, args=args, kwargs=kwargs)
        while True:
            do = self.iter(retry_state=retry_state)
            if isinstance(do, DoAttempt):
                try:
>                   result = fn(*args, **kwargs)

../../venv/lib/python3.7/site-packages/tenacity/__init__.py:361:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

args = ('rg1', 'm1'), kwargs = {}, cache_key = '9dcgFgzh/7XqPDLnkUe92F', rv = <MagicMock name='get_azure_compute_client().virtual_machines.get()' id='4401267984'>, found = False

    @functools.wraps(f)
    def decorated_function(*args, **kwargs):
        #: bypass cache
        if self._bypass_cache(unless, f, *args, **kwargs):
            return f(*args, **kwargs)

        try:
            cache_key = decorated_function.make_cache_key(
                f, *args, **kwargs
            )

            if (
                callable(forced_update)
                and (
                    forced_update(*args, **kwargs)
                    if wants_args(forced_update)
                    else forced_update()
                )
                is True
            ):
                rv = None
                found = False
            else:
                rv = self.cache.get(cache_key)
                found = True

                # If the value returned by cache.get() is None, it
                # might be because the key is not found in the cache
                # or because the cached value is actually None
                if rv is None:
                    # If we're sure we don't need to cache None values
                    # (cache_none=False), don't bother checking for
                    # key existence, as it can lead to false positives
                    # if a concurrent call already cached the
                    # key between steps. This would cause us to
                    # return None when we shouldn't
                    if not cache_none:
                        found = False
                    else:
                        found = self.cache.has(cache_key)
        except Exception:
            if self.app.debug:
                raise
            logger.exception("Exception possibly due to cache backend.")
            return f(*args, **kwargs)

        if not found:
            rv = f(*args, **kwargs)

            if response_filter is None or response_filter(rv):
                try:
                    self.cache.set(
                        cache_key,
                        rv,
>                       timeout=decorated_function.cache_timeout,
                    )

../../venv/lib/python3.7/site-packages/flask_caching/__init__.py:841:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <flask_caching.backends.simple.SimpleCache object at 0x105871410>, key = '9dcgFgzh/7XqPDLnkUe92F', value = <MagicMock name='get_azure_compute_client().virtual_machines.get()' id='4401267984'>, timeout = 60

    def set(self, key, value, timeout=None):
        expires = self._normalize_timeout(timeout)
        self._prune()
        self._cache[key] = (
            expires,
>           pickle.dumps(value, pickle.HIGHEST_PROTOCOL),
        )
E       _pickle.PicklingError: Can't pickle <class 'unittest.mock.MagicMock'>: it's not the same object as unittest.mock.MagicMock

../../venv/lib/python3.7/site-packages/flask_caching/backends/simple.py:76: PicklingError

The above exception was the direct cause of the following exception:

get_azure_compute_client = <MagicMock name='get_azure_compute_client' id='4400427728'>

    @patch("dev_maintenance.machines.get_azure_compute_client")
    def test_get_azure_machine_info (get_azure_compute_client):


        with app.app_context():
>           ret = get_azure_machine_info("rg1", "m1")

dev_maintenance/tests/test_machines.py:113:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../venv/lib/python3.7/site-packages/tenacity/__init__.py:292: in wrapped_f
    return self.call(f, *args, **kw)
../../venv/lib/python3.7/site-packages/tenacity/__init__.py:358: in call
    do = self.iter(retry_state=retry_state)
../../venv/lib/python3.7/site-packages/tenacity/__init__.py:332: in iter
    six.raise_from(retry_exc, fut.exception())
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

value = None, from_value = PicklingError("Can't pickle <class 'unittest.mock.MagicMock'>: it's not the same object as unittest.mock.MagicMock")

>   ???
E   tenacity.RetryError: RetryError[<Future at 0x106565850 state=finished raised PicklingError>]
<string>:3: RetryError
...