【发布时间】:2017-06-17 08:04:23
【问题描述】:
我正在构建一个执行特定 IO 绑定任务的脚本。我需要它来尝试下载大量数据集,在丢弃数据本身之前记录有关其大小的某些信息。
问题是我从中获取此数据的源不提供content-length 标头,因此无法事先知道文件大小。这要求我找到一种方法来监控下载过程需要多长时间,并且有一种方法可以终止该过程并继续其他此类进程,以防它花费太长时间(例如,超过 60 秒)。这是必要的,以避免“卡在”非常大的数据集上。
requests 不提供此内置功能,在花费大量时间寻找解决方案后,我决定通过pebble 库运行具有超时的并发进程。我的理解是,这是标准库 multiprocessing 模块的一个小扩展,它添加了一些安全功能,即错误处理和超时(这是我想要的)。
基于Process pool 示例,这是我的代码:
try:
with ProcessPool(max_workers=4) as pool:
iterator = pool.map(get_data, process_tuples[3:6], timeout=10)
while True:
try:
rows, cols, filesize, i = next(iterator)
datasets[i]['rows'] = rows
datasets[i]['columns'] = cols
datasets[i]['filesize'] = filesize
except TimeoutError as error:
print("Function took longer than %d seconds. Skipping responsible endpoint..." % error.args[1])
except StopIteration:
break
finally:
with open("../../../data/" + FILE_SLUG + "/glossaries/geospatial.json", "w") as fp:
json.dump(datasets, fp, indent=4)
但这在两个方面与预期行为不同:
- 我曾认为
timeout=10限制了每个单独的下载过程(由get_data完成)将花费的时间。但是,当我在一个大文件上运行它时,我收到一个TimeoutError,它指出我的过程花费了 30 多秒。 30 是我输入长度的 3 倍;这根本不是我想要的。那里发生了什么? - 当引发
TimeoutError时,进程不会放弃该运行并移至下一个(我想要的),而是跳转到finally块(我不想要的)。我认为这是对我的第一个问题的回答的结果。
【问题讨论】:
-
将
chunksize设置为 1,您将获得所需的 10 秒timeout。该库尚不支持您问题的第二点。我将很快重构该逻辑以支持此类用例。
标签: python concurrency python-multiprocessing