Skip to content

Commit 58cf648

Browse files
committed
v2.5.35: 优化部分下载失败时异常处理
1 parent e99af0c commit 58cf648

5 files changed

Lines changed: 38 additions & 18 deletions

File tree

assets/docs/sources/tutorial/0_common_usage.md

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,25 +82,38 @@ from jmcomic import *
8282
# 客户端
8383
client = JmOption.default().new_jm_client()
8484

85-
# 捕获jmcomic可能出现的异常
85+
# 捕获获取本子/章节详情时可能出现的异常
8686
try:
8787
# 请求本子实体类
8888
album: JmAlbumDetail = client.get_album_detail('427413')
8989
except MissingAlbumPhotoException as e:
9090
print(f'id={e.error_jmid}的本子不存在')
91-
91+
9292
except JsonResolveFailException as e:
9393
print(f'解析json失败')
9494
# 响应对象
9595
resp = e.resp
9696
print(f'resp.text: {resp.text}, resp.status_code: {resp.status_code}')
97-
97+
9898
except RequestRetryAllFailException as e:
9999
print(f'请求失败,重试次数耗尽')
100-
100+
101101
except JmcomicException as e:
102102
# 捕获所有异常,用作兜底
103103
print(f'jmcomic遇到异常: {e}')
104+
105+
# 多线程下载时,可能出现非当前线程下载失败,抛出异常,
106+
# 而JmDownloader有对应字段记录了这些线程发生的异常
107+
# 使用check_exception=True参数可以使downloader主动检查是否存在下载异常
108+
# 如果有,则当前线程会主动上抛一个PartialDownloadFailedException异常
109+
# 该参数主要用于主动检查部分下载失败的情况,
110+
# 因为非当前线程抛出的异常(比如下载章节的线程和下载图片的线程),这些线程如果抛出异常,
111+
# 当前线程是感知不到的,try-catch下载方法download_album不能捕获到其他线程发生的异常。
112+
try:
113+
album, downloader = download_album(123, check_exception=True)
114+
except PartialDownloadFailedException as e:
115+
downloader: JmDownloader = e.downloader
116+
print(f'下载出现部分失败, 下载失败的章节: {downloader.download_failed_photo}, 下载失败的图片: {downloader.download_failed_image}')
104117
```
105118

106119

src/jmcomic/api.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ def download_album(jm_album_id,
7979
def download_photo(jm_photo_id,
8080
option=None,
8181
downloader=None,
82-
callback=None):
82+
callback=None,
83+
check_exception=True,
84+
):
8385
"""
8486
下载一个章节(photo),参数同 download_album
8587
"""
@@ -91,7 +93,8 @@ def download_photo(jm_photo_id,
9193

9294
if callback is not None:
9395
callback(photo, dler)
94-
96+
if check_exception:
97+
dler.raise_if_has_exception()
9598
return photo, dler
9699

97100

src/jmcomic/jm_downloader.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ def all_success(self) -> bool:
193193
194194
注意!如果使用了filter机制,例如通过filter只下载3张图片,那么all_success也会为False
195195
"""
196-
if not self.has_no_download_failed_exception:
196+
if self.has_download_failures:
197197
return False
198198

199199
for album, photo_dict in self.download_success_dict.items():
@@ -207,8 +207,8 @@ def all_success(self) -> bool:
207207
return True
208208

209209
@property
210-
def has_no_download_failed_exception(self):
211-
return len(self.download_failed_image) == 0 and len(self.download_failed_photo) == 0
210+
def has_download_failures(self):
211+
return len(self.download_failed_image) != 0 or len(self.download_failed_photo) != 0
212212

213213
# 下面是回调方法
214214

@@ -268,7 +268,7 @@ def after_image(self, image: JmImageDetail, img_save_path):
268268
)
269269

270270
def raise_if_has_exception(self):
271-
if self.has_no_download_failed_exception:
271+
if not self.has_download_failures:
272272
return
273273
msg_ls = ['部分下载失败', '', '']
274274

src/jmcomic/jm_entity.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,6 @@ def is_album(cls):
3535
def is_page(cls):
3636
return False
3737

38-
@classmethod
39-
def __alias__(cls):
40-
# "JmAlbumDetail" -> "album" (本子)
41-
# "JmPhotoDetail" -> "photo" (章节)
42-
cls_name = cls.__name__
43-
return cls_name[cls_name.index("m") + 1: cls_name.rfind("Detail")].lower()
44-
4538

4639
class IndexedEntity:
4740
def getindex(self, index: int):
@@ -136,6 +129,13 @@ def __str__(self):
136129

137130
__repr__ = __str__
138131

132+
@classmethod
133+
def __alias__(cls):
134+
# "JmAlbumDetail" -> "album" (本子)
135+
# "JmPhotoDetail" -> "photo" (章节)
136+
cls_name = cls.__name__
137+
return cls_name[cls_name.index("m") + 1: cls_name.rfind("Detail")].lower()
138+
139139
@classmethod
140140
def get_dirname(cls, detail: 'DetailEntity', ref: str) -> str:
141141
"""
@@ -258,7 +258,7 @@ def is_image(cls):
258258
return True
259259

260260
def __str__(self):
261-
return f'''{self.__class__.__name__}({self.__alias__()}-[{self.download_url}])'''
261+
return f'''{self.__class__.__name__}(image-[{self.download_url}])'''
262262

263263
__repr__ = __str__
264264

src/jmcomic/jm_exception.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ class RequestRetryAllFailException(JmcomicException):
6262
class PartialDownloadFailedException(JmcomicException):
6363
description = '部分章节或图片下载失败异常'
6464

65+
@property
66+
def downloader(self):
67+
return self.from_context(ExceptionTool.CONTEXT_KEY_DOWNLOADER)
6568

6669
class ExceptionTool:
6770
"""
@@ -74,6 +77,7 @@ class ExceptionTool:
7477
CONTEXT_KEY_HTML = 'html'
7578
CONTEXT_KEY_RE_PATTERN = 'pattern'
7679
CONTEXT_KEY_MISSING_JM_ID = 'missing_jm_id'
80+
CONTEXT_KEY_DOWNLOADER = 'downloader'
7781

7882
@classmethod
7983
def raises(cls,

0 commit comments

Comments
 (0)