2

首先,我是 Python 新手。这与问题无关,但我不得不提一下。

我正在创建一个爬虫作为我的第一个项目,以了解 Python 中的工作原理,但到目前为止,这是我的主要问题......在使用requestsand时了解终端中的“如何获取多个进度条” pathos.multiprocessing

我设法完成了所有事情,我只想有更漂亮的输出,所以我决定添加进度条。我正在使用tqdm,因为我喜欢它的外观,而且它似乎最容易实现。

这是我的方法,目的是下载文件。

def download_lesson(self, lesson_data):
    if not 'file' in lesson_data:
        return print('=> Skipping... File {file_name} already exists.'.format(file_name=lesson_data['title']))

    response = requests.get(lesson_data['video_source'], stream=True)
    chunk_size = 1024

    with open(lesson_data['file'], 'wb') as file:
        progress = tqdm(
            total=int(response.headers['Content-Length']),
            unit='B',
            unit_scale=True
        )

        for chunk in response.iter_content(chunk_size=chunk_size):
            if chunk:
                progress.update(len(chunk))
                file.write(chunk)

        progress.close()
        print('=> Success... File "{file_name}" has been downloaded.'.format(file_name=lesson_data['title']))

我通过以下方式运行该方法Processing

# c = instance of my crawling class
# cs = returns the `lesson_data` for `download_lesson` method

p = Pool(1)
p.map(c.download_lesson, cs)

所以一切都很好,就像我processes=1Pool. 但是当我运行多个进程时,假设processes=3事情开始变得很奇怪,并且我在另一个进程中得到了多个进程。

我在tqdm 文档中发现有position. 这清楚地说明了我在这种情况下所需要的目的。

position : int, optional 指定打印此条的行偏移量(从 0 开始)如果未指定则自动。用于一次管理多个条形图(例如,从线程)。

但是,我不知道如何设置该位置。我尝试了一些奇怪的东西,例如添加一个应该自增一的变量,但是每当download_lesson运行该方法时,它似乎并没有做任何递增。总是0这样的位置总是0

所以在这种情况下我似乎不太了解......欢迎任何提示,提示或完整的解决方案。谢谢!


更新#1:

我发现我也可以将另一个参数传递给地图,所以我传递了正在设置的进程数量。(例如进程=2)

p = Pool(config['threads'])
p.map(c.download_lesson, cs, range(config['threads']))

因此,在我的方法中,我尝试打印出该参数,并且确实得到了0and 1,因为我正在运行2示例中的进程。

但这似乎根本没有做任何事情......

progress = tqdm(
    total=int(response.headers['Content-Length']),
    unit='B',
    unit_scale=True,
    position=progress_position
)

我仍然遇到相同的进度条重叠问题。当我手动将位置设置为(例如 10)时,它会在终端中跳转,因此位置确实会移动,但仍然会重叠 ofc,因为现在两者都设置为 10。但是当动态设置时,它似乎也不起作用。我不明白我的问题是什么......就像地图两次运行此方法时,它仍然为两个进度条提供最新的设置位置。我到底做错了什么?

4

1 回答 1

2

好的,首先我要感谢@MikeMcKerns 的评论......所以我的脚本有很多变化,因为我想要不同的方法,但最终归结为这些重要的变化

init.py现在看起来干净多了...

from scraper.Crawl import Crawl

if __name__ == '__main__':
    Crawl()

我在scraper.Crawl课堂上的方法 for download_lesson,现在看起来像这样......

def download_lesson(self, lesson):

    response = requests.get(lesson['link'], stream=True)
    chunk_size = 1024

    progress = tqdm(
        total=int(response.headers['Content-Length']),
        unit='B',
        unit_scale=True
    )

    with open(lesson['file'], 'wb') as file:
        for chunk in response.iter_content(chunk_size=chunk_size):
            progress.update(len(chunk))
            file.write(chunk)

    progress.close()

最后,我有一个专门用于多处理的方法,如下所示:

def begin_processing(self):
    pool = ThreadPool(nodes=Helper.config('threads'))

    for course in self.course_data:
        pool.map(self.download_lesson, course['lessons'])
        print(
            'Course "{course_title}" has been downloaded, with total of {lessons_amount} lessons.'.format(
                course_title=course['title'],
                lessons_amount=len(course['lessons'])
            )
        )

正如你所知道的,我对我的课程做了一些重大改变,但最重要的是我必须将这一点添加到我的课程中init.py

if __name__ == '__main__':

其次,我不得不使用@MikeMcKerns 建议我看的东西:

from pathos.threading import ThreadPool

因此,通过这些更改,我终于让一切都按我的需要工作了。这是一个快速截图。

在此处输入图像描述

即使如此,我仍然不知道为什么pathos.multiprocessing进展tqdm非常有问题,感谢迈克的建议,我设法解决了我的问题。谢谢!

于 2017-02-28T10:13:37.893 回答