Обработка сетевых ошибок
This commit is contained in:
parent
2ffd45d36e
commit
e435328907
4 changed files with 76 additions and 13 deletions
|
|
@ -74,6 +74,8 @@ usage: yandex-music-downloader [-h] [--quality <Качество>] [--skip-exist
|
|||
[--only-music]
|
||||
[--compatibility-level <Уровень совместимости>]
|
||||
[--timeout <Время ожидания>]
|
||||
[--tries <Количество попыток>]
|
||||
[--retry-delay <Задержка>]
|
||||
(--artist-id <ID исполнителя> | --album-id <ID альбома> | --track-id <ID трека> | --playlist-id <владелец плейлиста>/<тип плейлиста> | -u URL)
|
||||
[--unsafe-path] [--dir <Папка>]
|
||||
[--path-pattern <Паттерн>] --token <Токен>
|
||||
|
|
@ -100,8 +102,14 @@ options:
|
|||
--only-music Загружать только музыкальные альбомы (пропускать подкасты и аудиокниги)
|
||||
--compatibility-level <Уровень совместимости>
|
||||
Уровень совместимости, от 0 до 1. См. README для подробного описания (по умолчанию: 1)
|
||||
|
||||
Сетевые параметры:
|
||||
--timeout <Время ожидания>
|
||||
Время ожидания ответа от сервера, в секундах. Увеличьте если возникают сетевые ошибки (по умолчанию: 20)
|
||||
--tries <Количество попыток>
|
||||
Количество попыток при возникновении сетевых ошибок. 0 - бесконечное количество попыток (по умолчанию: 20)
|
||||
--retry-delay <Задержка>
|
||||
Задержка между повторными запросами при сетевых ошибках (по умолчанию: 5)
|
||||
|
||||
ID:
|
||||
--artist-id <ID исполнителя>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
|||
|
||||
[project]
|
||||
name = "yandex-music-downloader"
|
||||
version = "3.4.10"
|
||||
version = "3.5.0"
|
||||
description = "Загрузчик музыки с сервиса Яндекс.Музыка"
|
||||
requires-python = ">=3.9"
|
||||
readme = "README.md"
|
||||
|
|
|
|||
53
ymd/cli.py
53
ymd/cli.py
|
|
@ -6,7 +6,7 @@ import re
|
|||
import time
|
||||
import typing
|
||||
from argparse import ArgumentTypeError
|
||||
from collections.abc import Generator, Iterable
|
||||
from collections.abc import Callable, Generator, Iterable
|
||||
from pathlib import Path
|
||||
from typing import Optional, Union
|
||||
from urllib.parse import urlparse
|
||||
|
|
@ -52,17 +52,25 @@ def compatibility_level_arg(astr: str) -> int:
|
|||
)
|
||||
|
||||
|
||||
def natural_int_arg(astr: str) -> int:
|
||||
aint = int(astr)
|
||||
if aint > 0:
|
||||
return aint
|
||||
raise ArgumentTypeError("Значение должен быть > 0")
|
||||
def checked_int_arg(
|
||||
min_value: int, max_value: Optional[int] = None
|
||||
) -> Callable[[str], int]:
|
||||
def func(astr: str) -> int:
|
||||
aint = int(astr)
|
||||
if aint >= min_value and (max_value is None or aint <= max_value):
|
||||
return aint
|
||||
error_text = f"Значение должен быть >= {min_value}"
|
||||
if max_value is not None:
|
||||
error_text += f" и <= {max_value}"
|
||||
raise ArgumentTypeError(error_text)
|
||||
|
||||
return func
|
||||
|
||||
|
||||
def cover_resolution_arg(astr: str) -> int:
|
||||
if astr == "original":
|
||||
return -1
|
||||
return int(astr)
|
||||
return checked_int_arg(100)(astr)
|
||||
|
||||
|
||||
def lyrics_format_arg(astr: str) -> core.LyricsFormat:
|
||||
|
|
@ -115,7 +123,7 @@ def main():
|
|||
"--delay",
|
||||
default=DEFAULT_DELAY,
|
||||
metavar="<Задержка>",
|
||||
type=int,
|
||||
type=checked_int_arg(0),
|
||||
help=show_default("Задержка между запросами, в секундах"),
|
||||
)
|
||||
common_group.add_argument(
|
||||
|
|
@ -137,15 +145,33 @@ def main():
|
|||
f"Уровень совместимости, от {core.MIN_COMPATIBILITY_LEVEL} до {core.MAX_COMPATIBILITY_LEVEL}. См. README для подробного описания"
|
||||
),
|
||||
)
|
||||
common_group.add_argument(
|
||||
|
||||
network_group = parser.add_argument_group("Сетевые параметры")
|
||||
network_group.add_argument(
|
||||
"--timeout",
|
||||
metavar="<Время ожидания>",
|
||||
default=20,
|
||||
type=natural_int_arg,
|
||||
type=checked_int_arg(1),
|
||||
help=show_default(
|
||||
"Время ожидания ответа от сервера, в секундах. Увеличьте если возникают сетевые ошибки"
|
||||
),
|
||||
)
|
||||
network_group.add_argument(
|
||||
"--tries",
|
||||
metavar="<Количество попыток>",
|
||||
default=20,
|
||||
type=checked_int_arg(0),
|
||||
help=show_default(
|
||||
"Количество попыток при возникновении сетевых ошибок. 0 - бесконечное количество попыток"
|
||||
),
|
||||
)
|
||||
network_group.add_argument(
|
||||
"--retry-delay",
|
||||
metavar="<Задержка>",
|
||||
default=5,
|
||||
type=checked_int_arg(0),
|
||||
help=show_default("Задержка между повторными запросами при сетевых ошибках"),
|
||||
)
|
||||
common_group.add_argument("--debug", action="store_true", help=argparse.SUPPRESS)
|
||||
|
||||
id_group_meta = parser.add_argument_group("ID")
|
||||
|
|
@ -221,7 +247,12 @@ def main():
|
|||
print("Параметер url указан в неверном формате")
|
||||
return 1
|
||||
|
||||
client = core.init_client(args.token, args.timeout)
|
||||
client = core.init_client(
|
||||
token=args.token,
|
||||
timeout=args.timeout,
|
||||
max_try_count=args.tries,
|
||||
retry_delay=args.retry_delay,
|
||||
)
|
||||
result_tracks: Iterable[Track] = []
|
||||
|
||||
def album_tracks_gen(album_ids: Iterable[Union[int, str]]) -> Generator[Track]:
|
||||
|
|
|
|||
26
ymd/core.py
26
ymd/core.py
|
|
@ -1,6 +1,7 @@
|
|||
import datetime as dt
|
||||
import hashlib
|
||||
import re
|
||||
import time
|
||||
import typing
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
|
|
@ -33,6 +34,7 @@ from yandex_music import (
|
|||
Track,
|
||||
YandexMusicModel,
|
||||
)
|
||||
from yandex_music.exceptions import NetworkError
|
||||
|
||||
from ymd import api
|
||||
from ymd.api import (
|
||||
|
|
@ -91,9 +93,31 @@ class AlbumCover:
|
|||
mime_type: MimeType
|
||||
|
||||
|
||||
def init_client(token: str, timeout: int) -> Client:
|
||||
def init_client(
|
||||
token: str, timeout: int, max_try_count: int, retry_delay: int
|
||||
) -> Client:
|
||||
assert timeout > 0
|
||||
assert max_try_count >= 0
|
||||
assert retry_delay >= 0
|
||||
|
||||
client = Client(token)
|
||||
client.request.set_timeout(timeout)
|
||||
|
||||
original_wrapper = client.request._request_wrapper
|
||||
|
||||
def retry_wrapper(*args, **kwargs):
|
||||
try_count = 0
|
||||
while True:
|
||||
try:
|
||||
return original_wrapper(*args, **kwargs)
|
||||
except NetworkError as error:
|
||||
if max_try_count == 0 or try_count < max_try_count:
|
||||
try_count += 1
|
||||
time.sleep(retry_delay)
|
||||
continue
|
||||
raise error
|
||||
|
||||
client.request._request_wrapper = retry_wrapper
|
||||
return client.init()
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue